// DrawingGraphicalObjectsApplet.java (c) Kari Laitinen // http://www.naturalprogramming.com/ // 2007-01-21 File created. // 2008-02-29 Name changed GraphicalObject -> DrawableObject // 2008-02-29 Last modification. /* This program is a simple drawing tool with which you can draw graphical objects onto the screen. There is a menu which allows you to choose the type of the graphical object. This program demonstrates the following things: - the use of a class hierarchy that represents graphical objects such as curvy lines and circles - the use of the GeneralPath class to record mouse movements - the use of menus in a window whose drawings are painted onto a panel (This is a JPanel-based applet athough the word 'Panel' is not present in the file name.) */ import java.awt.* ; import java.awt.event.* ; import java.awt.geom.* ; // Classes GeneralPath etc. import javax.swing.* ; import java.util.ArrayList ; class DrawableObject { int line_thickness = 10 ; Color object_color = Color.black ; GeneralPath drawing_path = null ; Point2D.Double starting_point = null ; boolean object_is_completed = false ; public void mouse_pressed( Point mouse_position ) { drawing_path = new GeneralPath() ; starting_point = new Point2D.Double( mouse_position.x, mouse_position.y ) ; drawing_path.moveTo( mouse_position.x, mouse_position.y ) ; } public void mouse_dragged( Point mouse_position ) { if ( drawing_path != null ) { drawing_path.lineTo( mouse_position.x, mouse_position.y ) ; } } public void mouse_released( Point mouse_position ) { if ( drawing_path != null ) { object_is_completed = true ; } } // The following draw() method should be called at the beginning // of each subclass' redefined draw() method. public void draw( Graphics2D graphics2D ) { if ( object_is_completed == true ) { graphics2D.setPaint( object_color ) ; } else { graphics2D.setPaint( Color.red ) ; } graphics2D.setStroke( new BasicStroke( line_thickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) ) ; } } class CurvyLine extends DrawableObject { public CurvyLine( int given_line_thickness ) { line_thickness = given_line_thickness ; } public void draw( Graphics2D graphics2D ) { super.draw( graphics2D ) ; graphics2D.draw( drawing_path ) ; } } class Circle extends DrawableObject { public Circle( int given_line_thickness ) { line_thickness = given_line_thickness ; } public void draw( Graphics2D graphics2D ) { super.draw( graphics2D ) ; Point2D last_mouse_position = drawing_path.getCurrentPoint() ; int circle_radius = (int) starting_point.distance( last_mouse_position ) / 2 ; int circle_center_point_x = (int) ( ( starting_point.x + last_mouse_position.getX() ) / 2 ); int circle_center_point_y = (int) ( ( starting_point.y + last_mouse_position.getY() ) / 2 ); graphics2D.drawOval( circle_center_point_x - circle_radius, circle_center_point_y - circle_radius, 2 * circle_radius, 2 * circle_radius ) ; } } class GraphicalObjectsPanel extends JPanel implements MouseListener, MouseMotionListener { String selected_object_type = "Circle" ; int selected_line_thickness = 10 ; Color selected_drawing_color = Color.black ; DrawableObject object_being_drawn = null ; ArrayList objects_on_screen = new ArrayList() ; public GraphicalObjectsPanel() { // Event listeners must be registered. addMouseListener(this); addMouseMotionListener(this); } public void set_object_type( String given_object_type ) { selected_object_type = given_object_type ; } public void set_line_thickness( int given_line_thickness ) { selected_line_thickness = given_line_thickness ; } public void set_drawing_color( Color given_drawing_color ) { selected_drawing_color = given_drawing_color ; } // The following dummy methods are needed // to fully implement the listener interfaces. public void mouseMoved( MouseEvent event ) {} public void mouseClicked( MouseEvent event ) {} public void mouseEntered( MouseEvent event ) {} public void mouseExited( MouseEvent event ) {} public void mousePressed( MouseEvent event ) { if ( selected_object_type.equals( "CurvyLine" ) ) { object_being_drawn = new CurvyLine( selected_line_thickness ) ; } else if ( selected_object_type.equals( "Circle" ) ) { object_being_drawn = new Circle( selected_line_thickness ) ; } if ( object_being_drawn != null ) { object_being_drawn.mouse_pressed( event.getPoint() ) ; } } public void mouseDragged( MouseEvent event ) { if ( object_being_drawn != null ) { object_being_drawn.mouse_dragged( event.getPoint() ) ; repaint(); } } public void mouseReleased( MouseEvent event ) { if ( object_being_drawn != null ) { object_being_drawn.mouse_released( event.getPoint() ) ; objects_on_screen.add( object_being_drawn ) ; object_being_drawn = null ; repaint() ; } } // The painting method always draws all lines that have been printed. // The line that is not yet complete is drawn if object_being_drawn // points to a non-null object. public void paintComponent( Graphics graphics ) { super.paintComponent( graphics ) ; Graphics2D graphics2D = (Graphics2D) graphics ; for ( DrawableObject object_in_array : objects_on_screen ) { object_in_array.draw( graphics2D ) ; } if ( object_being_drawn != null ) { object_being_drawn.draw( graphics2D ) ; } } } public class DrawingGraphicalObjectsApplet extends JApplet implements ActionListener { JRadioButtonMenuItem draw_curvy_line_menu_item = new JRadioButtonMenuItem( "Curvy line" ) ; JRadioButtonMenuItem draw_circle_menu_item = new JRadioButtonMenuItem( "Circle" ) ; JRadioButtonMenuItem thin_line_menu_item = new JRadioButtonMenuItem( "Thin" ) ; JRadioButtonMenuItem thick_line_menu_item = new JRadioButtonMenuItem( "Thick" ) ; GraphicalObjectsPanel graphical_objects_panel = new GraphicalObjectsPanel() ; public void init() { // First we'll build a subnenu named "Select graphical object" draw_curvy_line_menu_item.addActionListener( this ) ; draw_circle_menu_item.addActionListener( this ) ; draw_circle_menu_item.setSelected( true ) ; ButtonGroup graphical_object_button_group = new ButtonGroup() ; graphical_object_button_group.add( draw_curvy_line_menu_item ) ; graphical_object_button_group.add( draw_circle_menu_item ) ; JMenu graphical_object_menu = new JMenu( "Select graphical object" ) ; graphical_object_menu.add( draw_curvy_line_menu_item ) ; graphical_object_menu.add( draw_circle_menu_item ) ; // Next we'll build a submenu named "Select line thickness" thin_line_menu_item.addActionListener( this ) ; thick_line_menu_item.addActionListener( this ) ; thick_line_menu_item.setSelected( true ) ; ButtonGroup line_thickness_button_group = new ButtonGroup() ; line_thickness_button_group.add( thin_line_menu_item ) ; line_thickness_button_group.add( thick_line_menu_item ) ; JMenu thickness_selection_menu = new JMenu( "Select line thickness" ) ; thickness_selection_menu.add( thin_line_menu_item ) ; thickness_selection_menu.add( thick_line_menu_item ) ; // Next we'll attach the submenus to the Settings menu. JMenu settings_menu = new JMenu( "Settings" ) ; settings_menu.add( graphical_object_menu ) ; settings_menu.add( thickness_selection_menu ) ; JMenuBar menubar_of_this_window = new JMenuBar() ; menubar_of_this_window.add( settings_menu ) ; setJMenuBar( menubar_of_this_window ) ; // The following line adds the JPanel-based object to this applet. getContentPane().add( graphical_objects_panel ) ; } public void actionPerformed( ActionEvent event ) { if ( event.getSource() instanceof JMenuItem ) { JMenuItem selected_menu_item = (JMenuItem) event.getSource() ; if ( selected_menu_item == draw_curvy_line_menu_item ) { graphical_objects_panel.set_object_type( "CurvyLine" ) ; } else if ( selected_menu_item == draw_circle_menu_item ) { graphical_objects_panel.set_object_type( "Circle" ) ; } else if ( selected_menu_item == thin_line_menu_item ) { graphical_objects_panel.set_line_thickness( 2 ) ; } else if ( selected_menu_item == thick_line_menu_item ) { graphical_objects_panel.set_line_thickness( 10 ) ; } } } }