Results 1 to 9 of 9
  1. #1
    Join Date
    Apr 2010
    Posts
    13
    Rep Power
    0

    Question How to draw and delete according to user input?

    Hello everybody,

    Currently I'm developing an app that should behave as follows:

    • The user will be presented with a frame. When the user clicks a button on the frame, the app must wait a certain amount of time, and draw a shape on the frame.
    • When the user clicks again (on the button or elsewhere), the shape must be deleted. After it has been deleted, the app will again wait for some time and then draw the shape.


    So, my approach to this was to write a class that extends JPanel, use a Timer and reimplement the paintComponent(Graphics g) method:

    I add the button to the JPanel, and I add an ActionListener to the button that sets up the timer and calls its start() method. I also add a MouseListener to the JPanel that on the mouseClicked(MouseEvent e) method calls repaint() and then resets the timer and calls its start() method.
    Then, on the paintComponent(Graphics g) method I call super.paintComponent(g), then check if I should paint a shape or delete it (I use a boolean for that, and set it to true or false as needed just before every call to repaint() or to the timer's start() method), like this:

    Java Code:
    protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (draw) {
                g.setColor(Color.BLACK);
                g.fillOval((getWidth()/2)-20,(getHeight()/2)-20,20,20);
            }else {
                g.clipRect(((getWidth()/2)-20,(getHeight()/2)-20,20,20);
            }     
        }
    As for the timer, I set its delay to the amount of time I want the app to wait before drawing, and its start() method merely calls repaint(), so the shape should be rendered after the timer's delay expires. But I don't know if it is, because the shape is not deleted upon producing a mouse click.

    This is the mouseClicked() method that I'm using:

    Java Code:
    public void mouseClicked(MouseEvent arg0) {        
                   draw = false;
                   repaint();
                   lapse = new Random().nextInt(results.getMaxLapse());
                   if (lapse < results.getMinLapse()) {
                       lapse = lapse+results.getMinLapse();
                   }
                   drawTimer.setDelay(lapse);
                   draw = true;
                   drawTimer.start();
            }
    And this is the button's ActionListener:

    Java Code:
    draw = true;
    drawTimer.setDelay(lapse);
    drawTimer.start();
    Both branches of the if statement in the paintComponent method explained above are executed when needed, so theoretically my app is deleting the shape. But I just don't see it. All I see is a black circle in the center of the screen, and I can click all I want but the circle will stay. Also, I'm fairly sure that the timer is not waiting the specified amount of time. And to top it off, the button is not rendered properly, I have to move the pointer on top of it to see it.

    The timer, the mouse listener and the action listener are all inner classes inside my JPanel subclass. The boolean (called "draw" in my code) and the timer's delay (called "lapse" in my code) are private fields on the JPanel subclass, and the Timer and the JButton have no modifiers, so if I'm not mistaken the inner classes should be able to work with them.

    Any idea as to what I'm doing wrong? Thanks in advance.

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    I suggest that you create a small compilable app that tries to do just this and nothing more, something that draws a very simple shape, nothing else, and have it be code that requires no other classes -- something that we can run unmodified on our systems, and post it here. This will be the best way to let us see just what you are doing, and possibly what you are doing wrong.

    Oh, and welcome to the forum!

    Best of luck!

  3. #3
    Join Date
    Apr 2010
    Posts
    13
    Rep Power
    0

    Default

    Quote Originally Posted by Fubarable View Post
    I suggest that you create a small compilable app that tries to do just this and nothing more, something that draws a very simple shape, nothing else, and have it be code that requires no other classes -- something that we can run unmodified on our systems, and post it here. This will be the best way to let us see just what you are doing, and possibly what you are doing wrong.

    Oh, and welcome to the forum!

    Best of luck!
    Thanks! Here's what you asked for:

    Java Code:
    package test;
    
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.util.Random;
    import javax.swing.JButton;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class SampleApp extends JPanel {
        
        private static final long serialVersionUID = 0L;
        JButton startButton;
        Timer drawTimer;
        private boolean testStarted = false;
        private boolean draw = false;
        private int currentIteration = 0;
        private int lapse = 0;
        
        public class ClickListener implements MouseListener {
        
            public void mouseClicked(MouseEvent arg0) {        
                if (testStarted) {
                draw = false;
                repaint();
                if (currentIteration < 5) {
                       currentIteration++;
                       lapse = new Random().nextInt(5000);
                       if (lapse < 1000) {
                           lapse = lapse+1000;
                       }
                       drawTimer.setDelay(lapse);
                       draw = true;
                       drawTimer.start();
                    }         
                }
            }
        
            public void mousePressed(MouseEvent arg0) {
            }
    
            public void mouseReleased(MouseEvent arg0) {
            }
    
            public void mouseEntered(MouseEvent arg0) {
            }
    
            public void mouseExited(MouseEvent arg0) {
            }
            
        }
            
        public class DrawTimerListener implements ActionListener {
            public void actionPerformed(ActionEvent arg0) {
                if (draw) {
                    repaint();
                }   
            }
        }
        
        public class StartButtonActionListener implements ActionListener {
    
            public void actionPerformed(ActionEvent arg0) {
                testStarted = true;
                startButton.setEnabled(false);
                currentIteration = 1;
                draw = true;
                drawTimer.setDelay(lapse);
                drawTimer.start();
            }
        }
    
           
        public static void main(String[] args) {
            try {           
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            } catch (IllegalAccessException ex) {
                ex.printStackTrace();
            } catch (InstantiationException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
            //Schedule a job for the event dispatch thread:
            //reading the configuration file and creating and showing the GUI.
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (draw) {
                g.setColor(Color.BLACK);
                g.fillOval((getWidth()/2)-20,(getHeight()/2)-20,20,20);
            }else {
                g.clipRect((getWidth()/2)-20,(getHeight()/2)-20,20,20);
            }     
        }
        
        /**
         * Create the GUI and show it.  For thread safety,
         * this method should be invoked from the
         * event dispatch thread.
         */
        private static void createAndShowGUI() {
            //Create and set up the window.
            JFrame frame = new JFrame("Sample App");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            //Create and set up the content pane.
            JComponent newContentPane = new SampleApp();
            newContentPane.setOpaque(true); //content panes must be opaque
            frame.setContentPane(newContentPane);
            //Display the window.
            frame.pack();        
            frame.setSize(640, 480);
            frame.setVisible(true);
        }
    
        public SampleApp() {
            super(new BorderLayout());
            drawTimer = new Timer(lapse,new DrawTimerListener());
            drawTimer.setRepeats(false);
            JPanel buttonPanel = new JPanel();
            startButton = new JButton("Start");
            startButton.addActionListener(new StartButtonActionListener());
            buttonPanel.add(startButton);
            add(buttonPanel,BorderLayout.PAGE_END);
            addMouseListener(new ClickListener());
        }        
    }
    There it is, my code stripped down just to draw and delete the circle five times, waiting between 1 and five seconds every time before actually drawing it. It compiles, and behaves exactly like my app. I hope that helps to locate the problem.

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    I would set the timer's initial delay, not the delay, and I would have the timer's actionPerformed be where draw is set to true followed by a repaint (because repaint calls may not be fully under your control).

    Also, why do you call g.clipRect(...)?

  5. #5
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    For example:
    Java Code:
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.Random;
    import javax.swing.JButton;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class SampleApp extends JPanel {
    
       private static final long serialVersionUID = 0L;
       JButton startButton;
       Timer drawTimer;
       private boolean testStarted = false;
       private boolean draw = false;
       private int currentIteration = 0;
       private int lapse = 0;
    
       public class ClickListener extends MouseAdapter {
          private Random random = new Random();
    
          public void mousePressed(MouseEvent arg0) {
             if (testStarted  && !drawTimer.isRunning()) {
                draw = false;
                repaint();
                if (currentIteration < 5) {
                   currentIteration++;
                   lapse = random.nextInt(4000) + 1000;
                   drawTimer.setInitialDelay(lapse);
                   drawTimer.start();
                }
             }
          }
       }
    
       public class DrawTimerListener implements ActionListener {
          public void actionPerformed(ActionEvent ae) {
             draw = true; 
             repaint();
          }
       }
    
       public class StartButtonActionListener implements ActionListener {
    
          public void actionPerformed(ActionEvent arg0) {
             testStarted = true;
             startButton.setEnabled(false);
             currentIteration = 1;
             drawTimer.setDelay(lapse);
             drawTimer.start();
          }
       }
    
       public static void main(String[] args) {
          try {
             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
          }
          catch (UnsupportedLookAndFeelException ex) {
             ex.printStackTrace();
          }
          catch (IllegalAccessException ex) {
             ex.printStackTrace();
          }
          catch (InstantiationException ex) {
             ex.printStackTrace();
          }
          catch (ClassNotFoundException ex) {
             ex.printStackTrace();
          }
          javax.swing.SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGUI();
             }
          });
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          if (draw) {
             g.setColor(Color.BLACK);
             g.fillOval((getWidth() / 2) - 20, (getHeight() / 2) - 20, 20, 20);
          }
          else {
             //!! g.clipRect((getWidth() / 2) - 20, (getHeight() / 2) - 20, 20, 20);
          }
       }
    
       private static void createAndShowGUI() {
          JFrame frame = new JFrame("Sample App");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          JComponent newContentPane = new SampleApp();
          newContentPane.setOpaque(true); //content panes must be opaque
          frame.setContentPane(newContentPane);
          frame.setPreferredSize(new Dimension(640, 480));
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public SampleApp() {
          super(new BorderLayout());
          drawTimer = new Timer(lapse, new DrawTimerListener());
          drawTimer.setRepeats(false);
          JPanel buttonPanel = new JPanel();
          startButton = new JButton("Start");
          startButton.addActionListener(new StartButtonActionListener());
          buttonPanel.add(startButton);
          add(buttonPanel, BorderLayout.PAGE_END);
          addMouseListener(new ClickListener());
       }
    }

  6. #6
    Join Date
    Apr 2010
    Posts
    13
    Rep Power
    0

    Default

    Quote Originally Posted by Fubarable View Post
    I would set the timer's initial delay, not the delay, and I would have the timer's actionPerformed be where draw is set to true followed by a repaint (because repaint calls may not be fully under your control).
    I'll try that tomorrow (it's late here, I should be using a pillow and a bed now, not a computer) and report back. Thanks for your help. ;)

    EDIT: Okay, I was posting while you were posting the fixed code. It seems to work correctly. I'll run it again tomorrow and we'll see.

    Also, why do you call g.clipRect(...)?
    That's the part that is supposed to delete the circle, since it fills the specified rectangle (which fully covers the circle) with the background color of the frame.
    Last edited by ProspectiveDeveloper; 04-22-2010 at 11:48 PM.

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by ProspectiveDeveloper View Post
    EDIT: Okay, I was posting while you were posting the fixed code. It seems to work correctly, except I think that the first time the circle is painted, it's painted immediately (that is, as if the timer's delay was zero). I'll run it again tomorrow and we'll see.
    That's because you're setting the initial delay to 0.


    That's the part that is supposed to delete the circle, since it fills the specified rectangle (which fully covers the circle) with the background color of the frame.
    Actually the super.paintComponent(g) will delete the circle just fine without the clipRect which deletes more than the circle -- it shrinks your clip to very small and deletes everything else!

  8. #8
    Join Date
    Apr 2010
    Posts
    13
    Rep Power
    0

    Default

    Quote Originally Posted by Fubarable View Post
    That's because you're setting the initial delay to 0.
    Yeah, just noticed that. I've edited my previous message while you were replying to take that part out since it's actually correct behaviour for that code...

    Actually the super.paintComponent(g) will delete the circle just fine without the clipRect which deletes more than the circle -- it shrinks your clip to very small and deletes everything else!
    Note to self: delete that clipRect on the real code.

    Once again, thanks for your help.

  9. #9
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by ProspectiveDeveloper View Post
    Once again, thanks for your help.
    You're welcome, and again, welcome to the forum. I hope to see you back asking questions and more importantly answering them! :)

Similar Threads

  1. User Input
    By brmcdani in forum New To Java
    Replies: 2
    Last Post: 02-05-2010, 01:59 AM
  2. how to get input from User
    By Alvaro in forum New To Java
    Replies: 7
    Last Post: 01-15-2010, 11:02 PM
  3. draw in jpanel using values input in textbox
    By New to JAVA in forum AWT / Swing
    Replies: 6
    Last Post: 07-08-2009, 11:06 AM
  4. User input- Pop Up Box
    By dedachi in forum AWT / Swing
    Replies: 3
    Last Post: 03-23-2009, 04:47 AM
  5. cant take input from user
    By new_1 in forum New To Java
    Replies: 6
    Last Post: 12-25-2007, 07:38 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •