Custom painting and mouse events

  • (2 Pages)
  • +
  • 1
  • 2

16 Replies - 2089 Views - Last Post: 07 March 2011 - 06:42 PM Rate Topic: -----

#1 bmcginnis  Icon User is offline

  • D.I.C Head

Reputation: 8
  • View blog
  • Posts: 130
  • Joined: 21-February 09

Custom painting and mouse events

Posted 06 March 2011 - 08:44 PM

In Program.java I have created a JToggleButton like so:
JToggleButton rectangleTool = new JToggleButton("Rectangle Tool");


In Canvas.java I have created a custom canvas that extends JPanel and implements MouseListener.
Part of Canvas.java is my override paintComponent, like so:
public void paintComponent(Graphics g)
{
     if(rectangleTool.isSelected() == true)
     {
          g.setColor(Color.blue);
          g.fillRect(x1, y1, w, h);
     }
}


As you can see, I'm trying to only paint the canvas if rectangleTool JToggleButton is selected.
The problem is rectangleTool is not recognized to exist in Canvas.java.

What would be the best way for me to pass variables from Program.java to Canvas.java so that I
could use them for custom painting/mouse events?

Thanks, Brian

Is This A Good Question/Topic? 0
  • +

Replies To: Custom painting and mouse events

#2 Dogstopper  Icon User is offline

  • The Ninjaducky
  • member icon



Reputation: 2872
  • View blog
  • Posts: 11,031
  • Joined: 15-July 08

Re: Custom painting and mouse events

Posted 06 March 2011 - 08:53 PM

In Program.java, you could make a method called getToggleState() or something like that and have it return true or false based on it's value. You can actually pass the Program object to the Canvas object through the constructor and the "this keyword.
Was This Post Helpful? 0
  • +
  • -

#3 bmcginnis  Icon User is offline

  • D.I.C Head

Reputation: 8
  • View blog
  • Posts: 130
  • Joined: 21-February 09

Re: Custom painting and mouse events

Posted 06 March 2011 - 09:11 PM

I'm not understanding what you mean exactly. Here was my best attempt at what you told me.

In Program.java I now have the following method:
public boolean getToggleState(JToggleButton button)
      {
         if(button.isSelected() == true)
         {
            return true;
         }
         else
         {
            return false;
         }
      }


In Canvas.java I have called that method:
public void paintComponent(Graphics g)
      {
         boolean tool = getToggleState(rectangleTool);
      
         if(tool == true)
         {
            g.setColor(Color.blue);
            g.fillRect(x1, y1, w, h);
         }
      }


Still run into the same problem though, I need to use divButton in Canvas.java but it is unknown to exist

This post has been edited by bmcginnis: 06 March 2011 - 09:19 PM

Was This Post Helpful? 0
  • +
  • -

#4 macosxnerd101  Icon User is offline

  • Self-Trained Economist
  • member icon




Reputation: 10567
  • View blog
  • Posts: 39,121
  • Joined: 27-December 08

Re: Custom painting and mouse events

Posted 06 March 2011 - 09:32 PM

First, you should always invoke the super.paintComponent() method when you override paintComponent() to handle important super class functionality.

Second, there is already a java.awt.Canvas. So not good practice to name your class the same thing as an existing class in the JDK.

I think this is the logic Dogstopper is trying to convey. Note how I invoke the isSelected() method on the Program object in your JPanel class.
class Program{
    private JToggleButton button;

    public boolean isSelected(){return button.isSelected();}
}

class Canvas extends JPanel{

     private Program program;

     Canvas(Program program){
          this.program = program;
     }

     public void paintComponent(Graphics g){
          super.paintComponent(g);
       
          if(program.isSelected()){
                //code
          }
     }
}


Was This Post Helpful? 0
  • +
  • -

#5 bmcginnis  Icon User is offline

  • D.I.C Head

Reputation: 8
  • View blog
  • Posts: 130
  • Joined: 21-February 09

Re: Custom painting and mouse events

Posted 06 March 2011 - 10:21 PM

Thanks for the reply macosxnerd, unfortunately when I tried your method I ended up with more errors than before :( Anyone else got an idea how I could solve this? Thanks.
Was This Post Helpful? 0
  • +
  • -

#6 macosxnerd101  Icon User is offline

  • Self-Trained Economist
  • member icon




Reputation: 10567
  • View blog
  • Posts: 39,121
  • Joined: 27-December 08

Re: Custom painting and mouse events

Posted 06 March 2011 - 10:22 PM

We're happy to help you debug. Post your full revised code and error messages. :)
Was This Post Helpful? 0
  • +
  • -

#7 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8332
  • View blog
  • Posts: 31,857
  • Joined: 06-March 08

Re: Custom painting and mouse events

Posted 06 March 2011 - 10:33 PM

public boolean getToggleState(JToggleButton button)
      {
         if(button.isSelected() == true)
         {
            return true;
         }
         else
         {
            return false;
         }
      }


should be
public boolean getToggleState(JToggleButton button)
      {
         return button.isSelected();
      }


Don't really need a method for that :)
You can tyoe
if(button.isSelected()) rathern than if(getToggleState(button))
Was This Post Helpful? 1
  • +
  • -

#8 bmcginnis  Icon User is offline

  • D.I.C Head

Reputation: 8
  • View blog
  • Posts: 130
  • Joined: 21-February 09

Re: Custom painting and mouse events

Posted 06 March 2011 - 10:59 PM

Thanks for the fast responses.

I created a method in Canvas.java and modified my paint method like so:
private Color rColor;
private Program prog = new Program(); 

public void rectangleColor(Color color)
{
     rColor = color;
}

public void paintComponent(Graphics g)
{
     super.paintComponent(g);

     if(prog.isRectSelect() == true)
     {
          g.setColor(rColor);
          g.fillRect(x1, y1, w, h);
     }
}



And in Program.java I've got the following:
private Canvas canvas = new Canvas();
private JToggleButton rectangleTool = new JToggleButton("Rectangle Tool");

public boolean isRectSelect()
{
     return rectangleTool.isSelected();
}



The rectangleColor method works fine and allows me to change the
color of the rectangles from Program.java. The issue arises when I
try to do the opposite, use data from Program.java in Canvas.java.

I get a StackOverflowError followed by 50+ lines of hoopla.
Was This Post Helpful? 0
  • +
  • -

#9 macosxnerd101  Icon User is offline

  • Self-Trained Economist
  • member icon




Reputation: 10567
  • View blog
  • Posts: 39,121
  • Joined: 27-December 08

Re: Custom painting and mouse events

Posted 06 March 2011 - 11:04 PM

You are instantiating a Canvas in Program, and a Program in Canvas, both as instance variables. This is a matter of which came first- the chicken or the egg. No need for Canvas to be in Program. Only a Program in Canvas. And also note how the Canvas constructor accepted a Program param in my example. It should only be concerned with the one specific instance passed to it. Not some random instance created with the Canvas, and isn't being displayed.
Was This Post Helpful? 0
  • +
  • -

#10 bmcginnis  Icon User is offline

  • D.I.C Head

Reputation: 8
  • View blog
  • Posts: 130
  • Joined: 21-February 09

Re: Custom painting and mouse events

Posted 06 March 2011 - 11:25 PM

This was just my most recent attempt, I tried you're idea exactly with the constructor that accepts type Program and all. With your idea though, I get this error instead: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
Was This Post Helpful? 0
  • +
  • -

#11 macosxnerd101  Icon User is offline

  • Self-Trained Economist
  • member icon




Reputation: 10567
  • View blog
  • Posts: 39,121
  • Joined: 27-December 08

Re: Custom painting and mouse events

Posted 06 March 2011 - 11:28 PM

It's not my suggestion, it's probably something in your implementation. My code above was just a skeleton designed to get across a concept. You still have to initialize the instance variables, should provide a constructor, etc.

Also, you're just posting segments of code. Please post ALL relevant code for us to debug, as well as the full stack trace. At the moment, we are the blind leading the blind. :)
Was This Post Helpful? 0
  • +
  • -

#12 bmcginnis  Icon User is offline

  • D.I.C Head

Reputation: 8
  • View blog
  • Posts: 130
  • Joined: 21-February 09

Re: Custom painting and mouse events

Posted 06 March 2011 - 11:40 PM

Sorry about that, here is all of the code

LayDes.java:
   import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   import javax.swing.border.*;

   public class LayDes extends JFrame implements ActionListener//, MouseListener
   {
      ImageIcon div = new ImageIcon("rectangle.gif");
   
      JMenu file = new JMenu("File");
      JMenuBar menuBar = new JMenuBar();
      JMenuItem open = new JMenuItem("Open");
      JMenuItem save = new JMenuItem("Save");
      JMenuItem saveAs = new JMenuItem("Save As");
      JMenuItem close = new JMenuItem("Close");
      JMenuItem exit = new JMenuItem("Exit");
   
      JToggleButton divButton = new JToggleButton(div);
   
      LayDesCanvas canvas = new LayDesCanvas();
      JPanel controls = new JPanel();
   
      //Container pane;
   
      public LayDes()
      {
         //pane = getContentPane();
      
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         setResizable(false);
         setSize(800, 600);
         setTitle("Layout Designer");
      
         //divButton.setBorderPainted(false);
         divButton.setFocusPainted(false);
         divButton.addActionListener(this);
      
         setJMenuBar(menuBar);
         menuBar.add(file);
      
         controls.add(divButton);
         controls.setBackground(Color.black);
         add(controls, BorderLayout.NORTH);
      
         add(canvas, BorderLayout.CENTER);
         //canvas.addMouseListener(this);
      
         file.add(open);
         file.add(save);
         file.add(saveAs);
         file.add(close);
         exit.addActionListener(this);
         file.addSeparator();
         file.add(exit);
      }
   
      public void actionPerformed(ActionEvent e)
      {
         if(e.getSource() == this.exit)
         {
            System.exit(0);
         }
      
         if(divButton.isSelected() == true)
         {
         	// DRAW <div> CODE //
            canvas.rectColor(Color.green);
         }
      }
   
      public boolean isDiv()
      {
         return divButton.isSelected();
      }
   
      /*public void mouseClicked(MouseEvent e)
      {
         if(e.getSource() == this.tableButton)
         {
            System.out.println("Table button clicked!");
         }
      }
   
      public void mouseEntered(MouseEvent e)
      {
         System.out.println("ENTERED");
         System.out.println(tableButton.isSelected());
      }
   
      public void mouseExited(MouseEvent e)
      {
         System.out.println("EXITED");
      }
   
      public void mousePressed(MouseEvent e)
      {
         System.out.println("PRESSED");
      }
   
      public void mouseReleased(MouseEvent e)
      {
         System.out.println("RELEASED");
      }
   
      public void paint(Graphics g){
         super.paint(g);
      
         g.setColor(Color.blue);
         g.drawLine(10, 10, 20, 20);
      }*/
   
      public static void main(String[] args)
      {
         new LayDes().setVisible(true);
      }
   }



LayDesCanvas.java:
   import java.awt.Color;
   import java.awt.Graphics;
   import java.awt.event.MouseEvent;
   import java.awt.event.MouseListener;
   import javax.swing.JPanel;

   //import java.awt.Point; If doing with Points, import this
   
   public class LayDesCanvas extends JPanel implements MouseListener
   {
      private int x1, y1, x2, y2, w, h;
      private Color rectangleColor = Color.red;
      private LayDes lay;
   
      //private Point start, end; If doing with Points, make these variables
   
      public LayDesCanvas()
      {
         addMouseListener(this);
      }
   
      LayDesCanvas(LayDes la)
      {
         this.lay = la;
      }
   
      public void rectColor(Color color)
      {
         rectangleColor = color;
      }
   
      public void mousePressed(MouseEvent e)
      {
         //start = e.getPoint(); Same, but done with Points
      
         x1 = e.getX();
         y1 = e.getY();
      }
   
      public void mouseReleased(MouseEvent e)
      {
         //end = e.getPoint(); Same, but done with Points
         //w = end.x - start.x;
         //h = end.y - start.y;
         //repaint();
      
         x2 = e.getX();
         y2 = e.getY();
         w = (x2 - x1);
         h = (y2 - y1);   
         repaint();
      }
   
      public void paintComponent(Graphics g)
      {
         super.paintComponent(g); //without this line everytime a new rectangle is created, the previous one gets deleted
      
         if(lay.isDiv() == true)
         {
            g.setColor(rectangleColor);
            g.fillRect(x1, y1, w, h);
         }
      }
   
      public void mouseExited(MouseEvent e){}
      public void mouseEntered(MouseEvent e){}
      public void mouseClicked(MouseEvent e){}
   }



And here are all the errors that pop up when I run the program (not when I compile, compiling works fine):

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at LayDesCanvas.paintComponent(LayDesCanvas.java:58)
at javax.swing.JComponent.paint(JComponent.java:1029)
at javax.swing.JComponent.paintChildren(JComponent.java:862)
at javax.swing.JComponent.paint(JComponent.java:1038)
at javax.swing.JComponent.paintChildren(JComponent.java:862)
at javax.swing.JComponent.paint(JComponent.java:1038)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:567)
at javax.swing.JComponent.paintChildren(JComponent.java:862)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5131)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:278)
at javax.swing.RepaintManager.paint(RepaintManager.java:1224)
at javax.swing.JComponent.paint(JComponent.java:1015)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
at java.awt.Container.paint(Container.java:1780)
at java.awt.window.paint(window.java:3375)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:796)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:713)
at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:693)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:125)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:642)
at java.awt.EventQueue.access$000(EventQueue.java:85)
at java.awt.EventQueue$1.run(EventQueue.java:603)
at java.awt.EventQueue$1.run(EventQueue.java:601)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:612)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at LayDesCanvas.paintComponent(LayDesCanvas.java:58)
at javax.swing.JComponent.paint(JComponent.java:1029)
at javax.swing.JComponent.paintChildren(JComponent.java:862)
at javax.swing.JComponent.paint(JComponent.java:1038)
at javax.swing.JComponent.paintChildren(JComponent.java:862)
at javax.swing.JComponent.paint(JComponent.java:1038)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:567)
at javax.swing.JComponent.paintChildren(JComponent.java:862)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5131)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:278)
at javax.swing.RepaintManager.paint(RepaintManager.java:1224)
at javax.swing.JComponent.paint(JComponent.java:1015)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
at java.awt.Container.paint(Container.java:1780)
at java.awt.window.paint(window.java:3375)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:796)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:713)
at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:693)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:125)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:642)
at java.awt.EventQueue.access$000(EventQueue.java:85)
at java.awt.EventQueue$1.run(EventQueue.java:603)
at java.awt.EventQueue$1.run(EventQueue.java:601)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:612)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Was This Post Helpful? 0
  • +
  • -

#13 bmcginnis  Icon User is offline

  • D.I.C Head

Reputation: 8
  • View blog
  • Posts: 130
  • Joined: 21-February 09

Re: Custom painting and mouse events

Posted 07 March 2011 - 12:35 AM

Alright, so I've been playing around and am getting some funny output.

Heres the part of code I modified:
public void paintComponent(Graphics g)
{
     super.paintComponent(g); //without this line everytime a new rectangle is created, the previous one gets deleted

     lay = new LayDes();

     if(lay.isDiv() == true)
     {
          g.setColor(rectangleColor);
          g.fillRect(x1, y1, w, h);
     }
}



All I did was add "lay = new LayDes();" and it now compiles and runs without errors. However, isDiv() is only
returning false even when it's true. :( This is so stressful does anyone kno why it's doing this?
Was This Post Helpful? 0
  • +
  • -

#14 Dogstopper  Icon User is offline

  • The Ninjaducky
  • member icon



Reputation: 2872
  • View blog
  • Posts: 11,031
  • Joined: 15-July 08

Re: Custom painting and mouse events

Posted 07 March 2011 - 04:22 AM

In Program.java, you have this:
private Canvas canvas = new Canvas();


What I was saying was that you need to pass the current instance of program to the Canvas...like this:

private Canvas canvas = new Canvas(this);



From there, you can use the code that macosxnerd101 gave you in post #4:
http://www.dreaminco...ost__p__1272680
Was This Post Helpful? 0
  • +
  • -

#15 bmcginnis  Icon User is offline

  • D.I.C Head

Reputation: 8
  • View blog
  • Posts: 130
  • Joined: 21-February 09

Re: Custom painting and mouse events

Posted 07 March 2011 - 06:05 AM

Thanks for the reply dogstopper. I think that there must be some other problem at hand.

With the code done the way that macosxnerd said, I changed the line that you told me from:
LayDesCanvas canvas = new LayDesCanvas();

To:
LayDesCanvas canvas = new LayDesCanvas(this);

And now, none of my mouseevents for my canvas seem to work. For example in LayDesCanvas.java
i have the following code:
public void mouseClicked(MouseEvent e)
      {
         System.out.println(lay.isDiv());
         System.out.println(lay.isDiv());
         System.out.println(lay.isDiv());
         System.out.println(lay.isDiv());
      }


However, nothing happens when I click the mouse... strange. Yes i have the proper imports and yes class implements MouseListener.
One problem just keeps leading me to another :( Anyone else have an idea?

This post has been edited by bmcginnis: 07 March 2011 - 06:06 AM

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2