Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 7 of 7

Thread: How to detect mouse event while painting in a loop

  1. #1
    Junior Member
    Join Date
    Feb 2011
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Question How to detect mouse event while painting in a loop

    Hi everyone,

    I really need your help with this. I have a JFrame and a JPanel in it. In the overridden paint event of the JPanel, I draw thousands of different shapes (lines, etc.) - I loop in a set of shapes actually. I need the code in my drawing loop to detect a mouse event and stop; in other words, if I click (or move, etc.) the mouse, I need my code to know that and react by, say exiting the loop immediately. I tried with multithreading, timers, etc. and didn't get satisfying results.

    Any help or code example would be much appreciated.

    By the way, is there a way to capture mouse events by more than one thread at the same time. If I could have a second thread monitoring the mouse and updating a variable which would also be checked inside the loop, at each iteration...??

    Thanks
    Robert


  2. #2
    Crazy Cat Lady KevinWorkman's Avatar
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    5,424
    My Mood
    Hungover
    Thanks
    144
    Thanked 636 Times in 540 Posts

    Default Re: How to detect mouse event while painting in a loop

    That's an interesting problem. I would perhaps use a BufferedImage, and draw one shape at a time to it (in a synchronized block), then call repaint() after each shape is drawn to the image. In paintComponent(), draw the image in another block, synchronized to the same thing as the drawing to the image is. That way you aren't constantly tying up the EDT, which will hopefully give you a chance to catch the events. I'm really not sure though. If you provide an SSCCE, perhaps we can experiment with it.
    Useful links: How to Ask Questions the Smart Way | Use Code Tags | Java Tutorials
    Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!

  3. The Following User Says Thank You to KevinWorkman For This Useful Post:

    r9reen (February 25th, 2011)

  4. #3
    Junior Member
    Join Date
    Feb 2011
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Question Re: How to detect mouse event while painting in a loop

    Quote Originally Posted by KevinWorkman View Post
    That's an interesting problem. I would perhaps use a BufferedImage, and draw one shape at a time to it (in a synchronized block), then call repaint() after each shape is drawn to the image. In paintComponent(), draw the image in another block, synchronized to the same thing as the drawing to the image is. That way you aren't constantly tying up the EDT, which will hopefully give you a chance to catch the events. I'm really not sure though. If you provide an SSCCE, perhaps we can experiment with it.
    Thank you Kevin. I tested what you suggested thoroughly. Before calling repaint() in the loop, I test a boolean variable to see if I should break the loop or continue. The same boolean is set to true when the mouse moves (in listener attached to the jframe). Unfortunately, calling repaint() doesn't seem to untie the EDT to intercept mouse events appropriately. Another issue is the overhead of redrawing the same image at each iteration of the loop. In win32, I used to call PeekMessage() or use multithreading to solve such issues; is there a method somewhere in java to test the mouse state at any time? If not, can I intercept mouse events in another thread somehow?

    Thanks a lot
    Robert

  5. #4
    Crazy Cat Lady KevinWorkman's Avatar
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    5,424
    My Mood
    Hungover
    Thanks
    144
    Thanked 636 Times in 540 Posts

    Default Re: How to detect mouse event while painting in a loop

    Hmm. I'd be interested in seeing an SSCCE that I could play with. This is an interesting problem.
    Useful links: How to Ask Questions the Smart Way | Use Code Tags | Java Tutorials
    Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!

  6. #5
    Junior Member
    Join Date
    Feb 2011
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Default Re: How to detect mouse event while painting in a loop

    Quote Originally Posted by KevinWorkman View Post
    Hmm. I'd be interested in seeing an SSCCE that I could play with. This is an interesting problem.
    OK. In the following code, the mouseMoved() method resets the line count to zero. When this happens (when the mouse moves), I want the painting of lines to restart from the beginning immediately. Obviously, this doesn't happen if you run the code, may be because repaint() is asynchronous.. As you can see, I also tried to call paintComponent() directly, to draw the image from the loop, or call update() without achieving the desired effect which is -- once again: erase the panel background with the black pen and redraw in white from the 1st line IMMEDIATELY as soon as the mouse moves.

    I really appreciate your help. Thanks.

    Robert

    PS. Please copy/paste in Eclipse, select all and reformat using ctrl+shift+F / no idea with other editors. The java file should be named SyncPaint.java. For some reason, the EXIT_ON_CLOSE token is not posted correctly below, please edit the token manually, sorry. BTW, do you know a link explaining how to post code correctly here please??

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Insets;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.Line2D;
    import java.awt.image.BufferedImage;
     
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
    @SuppressWarnings("serial")
    class SyncPaintPanel extends JPanel {
     
        private BufferedImage paintImage = null;
        private Line2D[] linesArray;
        private int lineCount;
     
        SyncPaintPanel(JFrame frame, int width, int height) {
     
            int w, h;
     
            Insets insets = frame.getInsets();
     
            w = frame.getWidth() - insets.left - insets.right;
            h = frame.getHeight() - insets.top - insets.bottom;
     
            setSize(w, h);
     
            linesArray = new Line2D[h];
     
            for (int i = 0; i < h; i++) {
                linesArray[i] = new Line2D.Double(i*w/h, i, w - i*w/h - 1, i);
            }
     
            addMouseMotionListener(new SyncMouseListener());
        }
     
        void refresh() {
     
            if (paintImage == null) {
                paintImage = (BufferedImage) createImage(getWidth(), getHeight());
            }
     
            Graphics2D g2d = paintImage.createGraphics();
     
            lineCount = 0;
     
            while(lineCount < getHeight()) {
     
                if(lineCount == 0) {
     
                    g2d.setColor(Color.black);
                    g2d.fillRect(0, 0, getWidth(), getHeight());
     
                    //paintComponent(getGraphics());
                    //getGraphics().drawImage(paintImage, 0, 0, this);
                    //update(getGraphics());
                    repaint(0);
     
                    g2d.setColor(Color.white);
                }
     
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
     
                g2d.draw(linesArray[lineCount++]);
                repaint(0);
            }
     
            g2d.dispose();
     
        }
     
        public void paintComponent(Graphics g) {
     
            if (paintImage != null) {
                g.drawImage(paintImage, 0, 0, this);
            }
     
        }
     
        class SyncMouseListener extends MouseAdapter {
     
            public void mouseMoved(MouseEvent e) {
                //System.out.println("mouse move");
                lineCount = 0;
            }
     
        }
     
    }
     
    public class SyncPaint {
     
        public static void main(String[] args) {
     
            JFrame frame = new JFrame("SyncPaint");
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(null);
            frame.setSize(400, 600);
            SyncPaintPanel panel = new SyncPaintPanel(frame, frame.getWidth(),
                    frame.getHeight());
            frame.add(panel);
     
            panel.refresh();
        }
     
    }
    Last edited by KevinWorkman; February 28th, 2011 at 11:08 AM. Reason: added highlight tags

  7. #6
    Crazy Cat Lady KevinWorkman's Avatar
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    5,424
    My Mood
    Hungover
    Thanks
    144
    Thanked 636 Times in 540 Posts

    Default Re: How to detect mouse event while painting in a loop

    I don't normally do this, but I've modified your code to show you one way to accomplish your goal. The solution is relatively simple, but let me know if anything doesn't make sense.

    I also edited your post to include the highlight tags.


    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Insets;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.Line2D;
     
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
     
    @SuppressWarnings("serial")
    class SyncPaintPanel extends JPanel {
     
    	private Line2D[] linesArray;
     
    	private int linesToDraw = 0;
     
    	Timer timer = new Timer(10, new ActionListener(){
    		public void actionPerformed(ActionEvent e){
    			if(linesToDraw < linesArray.length){
    				linesToDraw++;
    			}
    			else{
    				timer.stop();
    			}
    			repaint();
    		}
    	});
     
    	SyncPaintPanel(JFrame frame, int width, int height) {
     
    		int w, h;
     
    		Insets insets = frame.getInsets();
     
    		w = frame.getWidth() - insets.left - insets.right;
    		h = frame.getHeight() - insets.top - insets.bottom;
     
    		setSize(w, h);
     
    		linesArray = new Line2D[h];
     
    		for (int i = 0; i < h; i++) {
    			linesArray[i] = new Line2D.Double(i*w/h, i, w - i*w/h - 1, i);
    		}
     
    		addMouseMotionListener(new SyncMouseListener());
     
    		timer.start();
    	}
     
    	public void paintComponent(Graphics g) {
     
    		super.paintComponent(g);
     
    		for(int lineCount = 0; lineCount < linesToDraw; lineCount++) {
    			((Graphics2D)g).draw(linesArray[lineCount]);			
    		}
    	}
     
    	class SyncMouseListener extends MouseAdapter {
     
    		public void mouseMoved(MouseEvent e) {
    			linesToDraw = 0;
    			timer.start();
    		}
    	}
    }
     
    public class SyncPaint {
     
    	public static void main(String[] args) {
     
    		JFrame frame = new JFrame("SyncPaint");
    		frame.setVisible(true);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setLayout(null);
    		frame.setSize(400, 600);
    		SyncPaintPanel panel = new SyncPaintPanel(frame, frame.getWidth(),
    				frame.getHeight());
    		frame.add(panel);
     
    	}
     
    }
    Useful links: How to Ask Questions the Smart Way | Use Code Tags | Java Tutorials
    Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!

  8. #7
    Junior Member
    Join Date
    Feb 2011
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Default Re: How to detect mouse event while painting in a loop

    Thank you Kevin for the great code! Meanwhile I found another solution using a buffered image (as you suggested) and no timers. I post it here for the record.

    You made my day!

    Robert

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Insets;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.Line2D;
    import java.awt.image.BufferedImage;
     
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
    @SuppressWarnings("serial")
    class SyncPaintPanel extends JPanel {
     
        private BufferedImage paintImage = null;
        private Line2D[] linesArray;
        private int lineCount, reset;
     
        SyncPaintPanel(JFrame frame, int width, int height) {
     
            int w, h;
     
            Insets insets = frame.getInsets();
     
            w = frame.getWidth() - insets.left - insets.right;
            h = frame.getHeight() - insets.top - insets.bottom;
     
            setSize(w, h);
     
            linesArray = new Line2D[h];
     
            for (int i = 0; i < h; i++) {
                linesArray[i] = new Line2D.Double(i*w/h, i, w - i*w/h - 1, i);
            }
     
            addMouseMotionListener(new SyncMouseListener());
        }
     
        void refresh() {
     
            if (paintImage == null) {
                paintImage = (BufferedImage) createImage(getWidth(), getHeight());
            }
     
            Graphics2D g2d = paintImage.createGraphics();
     
            reset = 1;
            lineCount = 0;
     
            while(lineCount < getHeight()) {
     
                if(reset == 1) {
     
                    reset = 0;
                    lineCount = 0;
     
                    System.out.println("reset");
     
                    g2d.setColor(Color.black);
                    g2d.fillRect(0, 0, getWidth(), getHeight());
     
                    g2d.setColor(Color.white);
                }
     
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
     
                System.out.println("drawing line " + lineCount);
                g2d.draw(linesArray[lineCount++]);
                paintImmediately(0, 0, getWidth(), getHeight());
            }
     
            g2d.dispose();
     
        }
     
        public void paintComponent(Graphics g) {
     
            if (paintImage != null) {
                g.drawImage(paintImage, 0, 0, this);
            }
     
        }
     
        class SyncMouseListener extends MouseAdapter {
     
            public void mouseMoved(MouseEvent e) {
                System.out.println("mouse move");
                reset = 1;
            }
     
        }
     
    }
     
    public class SyncPaint {
     
        public static void main(String[] args) {
     
            JFrame frame = new JFrame("SyncPaint");
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(null);
            frame.setSize(400, 600);
            SyncPaintPanel panel = new SyncPaintPanel(frame, frame.getWidth(),
                    frame.getHeight());
            frame.add(panel);
     
            panel.refresh();
        }
     
    }

Similar Threads

  1. [SOLVED] Detect USB signal
    By mine0926 in forum Java Native Interface
    Replies: 2
    Last Post: February 4th, 2011, 07:46 PM
  2. detect duplicated programs
    By pulsarsitra in forum Java Theory & Questions
    Replies: 0
    Last Post: January 13th, 2011, 11:54 AM
  3. Automating a Mouse Event
    By zarov in forum Java Theory & Questions
    Replies: 1
    Last Post: December 11th, 2010, 01:42 AM
  4. [SOLVED] Extends JPanel painting problem
    By Philip in forum What's Wrong With My Code?
    Replies: 3
    Last Post: July 28th, 2010, 03:16 PM
  5. How can I detect the end of a line in a file ?
    By lumpy in forum Java Theory & Questions
    Replies: 3
    Last Post: February 18th, 2010, 03:13 AM

Tags for this Thread