Java Tutorial: Painting in swing components, part 2 (Interactive painting)

View previous topic View next topic Go down

Java Java Tutorial: Painting in swing components, part 2 (Interactive painting)

Post by BIT0102-Mohaimin on Thu Oct 21, 2010 10:04 pm

You are requested to read Painting in swing components, part 1 before you read this.

As you already know the basic of swing painting, I think it is time to discuss something advanced. In this tutorial, we will let the user draw some geometric figures on a JPanel using mouse.

As usual, we will directly go through codes. Lets start.
I am working in a package painting for all tutorials under Painting in swing components. If you want to be with me, you better create that also. For this particular tutorial (I mean, part 2), we will write three public classes under sub package mousedrag. Go through the code, you'll be clear about the package hierarchy.

Code:

package painting.mousedrag;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;

/*
 * First of all, lets create a paper on which we will draw.
 */
public class Paper extends JPanel {
   // These two Points hold the coordinates of the line to
   // draw
   private Point   from, to;

   // The mode lets the paper know what should be drawn.
   // This will be explained later.
   private int      mode   = LINE_MODE;
   public static final int   LINE_MODE   = 1, RECTANGLE_MODE = 2, OVAL_MODE = 3;

   public Paper() {
      // These two initializations are not necessary, but
      // I prefer initializing all objects to avoid risk
      // of NullPointerException
      from = new Point();
      to = new Point();

      // Take a look at the inner class Pencil bellow,
      // after that come back here again
      Pencil pencil = new Pencil();
      addMouseListener(pencil);
      addMouseMotionListener(pencil);

      // See, we have added both MouseListener and
      // MouseMotionListener. I think its clear why...
   }

   // Overriding paintComponent().
   @Override
   protected void paintComponent(Graphics g) {
      // You should always call super class's painting
      // method whenever you override them. Those methods
      // checks possible exceptions and returns from the
      // correct place. If you do not call the super class
      // method, there is a big possibility to experience
      // unexpected occurrences.
      super.paintComponent(g);

      // Depending on the mode, a geometric figure will be
      // drawn
      switch (mode) {
         case LINE_MODE:
            g.drawLine(from.x, from.y, to.x, to.y);
            break;
         case RECTANGLE_MODE:
            g.drawRect(from.x, from.y, to.x - from.x, to.y - from.y);
            break;
         case OVAL_MODE:
            g.drawOval(from.x, from.y, to.x - from.x, to.y - from.y);
            break;
      }
   }

   // You can set the mode from outside the code.
   public void setMode(int mode) {
      this.mode = mode;
   }

   /**
    * MouseAdapter is a Class that implements (blank) all
    * methods of MouseListener and MouseMotionListener. I
    * did not implement those two interfaces directly
    * because that would require to implement all 7 methods
    * of the two interfaces where 5 would be blank. Like
    * MouseAdapter, Adapter to other EventListener classes
    * are also available. Using adapters makes your program
    * neat and clean.
    */
   class Pencil extends MouseAdapter {
      // mousePressed() is declared in MouseListener.
      @Override
      public void mousePressed(MouseEvent event) {
         // A mouse press indicates starting point of the
         // figure you want to draw.
         from = event.getPoint();
         // MouseEvent.getPoint() returns the coordinate
         // of the Component where Event (here,
         // mouse-press) has occurred
      }

      // mouseDragged() is declared in MouseMotionListener
      @Override
      public void mouseDragged(MouseEvent event) {
         // When you drag mouse to some place, the figure should
         // be redrawn, So, repaint is called, which
         // calls paintComponent().
         to = event.getPoint();
         repaint();
      }

      // Now, let's back to Paper()
   }
}

Code:

package painting.mousedrag;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JToolBar;

/**
 * Here we are creating a ClipBoard (JFrame) to hold our
 * paper. We can control our drawing mode from here
 */
public class ClipBoard extends JFrame implements ActionListener {
   private Paper      paper;
   private JTextField   statusBar;

   public ClipBoard() {
      super("Interactive Painting");
      paper = new Paper();

      // The status bar will display the current paint
      // mode.
      statusBar = new JTextField("Line mode");

      decorate();
   }

   // This method do necessary things to decorate the
   // window
   private void decorate() {
      JToolBar toolbar = new JToolBar(); // The tool bar
      // will help to
      // select the
      // mode

      // Buttons in the tool bar
      JButton lineDraw = new JButton("Line");
      JButton rectDraw = new JButton("Rectangle");
      JButton ovalDraw = new JButton("Oval");

      // ActionListener (Implemented bellow) are added to
      // the buttons
      lineDraw.addActionListener(this);
      rectDraw.addActionListener(this);
      ovalDraw.addActionListener(this);

      // Buttons added to tool bar
      toolbar.add(lineDraw);
      toolbar.add(rectDraw);
      toolbar.add(ovalDraw);

      // We don't want the user manually edit the status
      // bar, right?
      statusBar.setEditable(false);

      // I personally do not prefer a floating tool bar.
      // Floating means, you can drag it from its original
      // position. Set the parameter to true to check the
      // difference
      toolbar.setFloatable(false);

      /*
       * If you are a beginner, you may not know that a
       * JFrame's default Layout is BorderLayout. We have
       * used the default one so we did not have to set
       * layout manually. Default layout of JPanel and
       * most other JComponents is FlowLayout
       */

      add(toolbar, BorderLayout.NORTH); // Tool bar should
      // be at the top
      add(statusBar, BorderLayout.SOUTH); // Status bar at
      // the bottom
      add(paper);
      // Paper set no where! Nope, The default position is
      // center. The paper is set at center.
   }

   @Override
   public void actionPerformed(ActionEvent ae) {
      // You can set an action command (a String) in a
      // button, if you set nothing, the text in the
      // button is set as action command by default. We
      // have extracted the action command to identify
      // which button was pressed.
      if (ae.getActionCommand().equals("Line")) {
         paper.setMode(Paper.LINE_MODE);
         statusBar.setText("Line mode");
      } else if (ae.getActionCommand().equals("Rectangle")) {
         paper.setMode(Paper.RECTANGLE_MODE);
         statusBar.setText("Rectangle Mode");
      } else if (ae.getActionCommand().equals("Oval")) {
         paper.setMode(Paper.OVAL_MODE);
         statusBar.setText("Oval Mode");
      }
   }
}

Code:

package painting.mousedrag;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

/**
 * Here is a test execute.
 */
public class TestExecute {
   public static void main(String[] args) {
      // Setting a look and feel, Java default look and
      // feel looks boring to me.
      try {
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
         // Well, as you can see, I have set the system
         // look and feel in our program. This will let
         // the users feel our tool as their own.
         // System look and feel means actually the theme
         // you have set in your operating system

         // The all four exceptions handled bellow are
         // mandatory. If for some reason look and feel
         // can not be set, a message is displayed
      } catch (ClassNotFoundException e) {
         JOptionPane.showMessageDialog(null,
               "Failed to initialize look and feel, default used");
      } catch (InstantiationException e) {
         JOptionPane.showMessageDialog(null,
               "Failed to initialize look and feel, default used");
      } catch (IllegalAccessException e) {
         JOptionPane.showMessageDialog(null,
               "Failed to initialize look and feel, default used");
      } catch (UnsupportedLookAndFeelException e) {
         JOptionPane.showMessageDialog(null,
               "Failed to initialize look and feel, default used");
      }

      JFrame frame = new ClipBoard();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(400, 300);

      // Make sure you set the window visible after all
      // necessary decorations are set. To check what
      // happens otherwise, put it before the setSize() is
      // called.

      // There is possibility that you will find no change
      // because the frame contains very few components.
      frame.setVisible(true);
   }
}

There is a little limitation in this simple drawing tool. Find it and solve it.

Thats all about today. Before saying good bye, I think I should I should thank Farhan for this problem he posted. I was encouraged by his problem to write this tutorial.


Last edited by LordAmit on Thu Oct 21, 2010 11:42 pm; edited 1 time in total (Reason for editing : Please follow the structure <programming language> Tutorial: Tutorial name)
avatar
BIT0102-Mohaimin
Programmer
Programmer

Course(s) :
  • BIT

Blood Group : B+
Posts : 415
Points : 715

View user profile

Back to top Go down

View previous topic View next topic Back to top


 
Permissions in this forum:
You cannot reply to topics in this forum