javaswinggraphicsmouseclick-eventclick-counting

Why my mouseClicked() counter increments by 2?


I am trying to count mouseClicks, but I don't understand why my counter gets incremented by 2 every click. Tried getClickCount(), but it also is not what I need.

My goal after counting: I would use the counter to paint different things at different clickcount. Lets say 1st and 2nd would always get coordinates to drawLine() and 3rd click would drawRect().

package graphics_training_painting;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JFrame;

public class U4 extends Canvas implements MouseListener{
    private int x1;
    private int y1;
    private int x2;
    private int y2;
    private int counter = 0;

    public U4() {
        setBackground(Color.white);
    }

    public static void main(String[] args) {
        U4 u = new U4();
        JFrame f = new JFrame();
        f.add(u);
        f.setSize(800, 600);
        f.setVisible(true);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        counter++;
        System.out.println(counter);
    }

    @Override
    public void mouseEntered(MouseEvent e) {


    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent e) {
/*      x1 = e.getX();
        y1 = e.getY();*/
    }

    @Override
    public void mouseReleased(MouseEvent e) {
/*      x2 = e.getX();
        y2 = e.getY();
        repaint();*/        
    }

    public void paint(Graphics g) {
        addMouseListener(this);
        g.setColor(Color.blue);
        g.drawLine(x1, y1, x2, y2);

    }   
}

Thank you a lot for help or suggestions, Timmy!


Solution

  • Don't add your MouseListener in your paint Method! That will add many listeners each incrementing the counter when activated.

    You need to know that you do not have control over when or if paint will be called, and it is likely to be called many times during a typical program run. For this reason and others, you should not put program logic, state change code, or component creation inside of this method. Add your MouseListener in some initialization code, such as a constructor, that is called once.

    As an aside, you will not want to mix AWT and Swing components as you're doing. Instead you should have your U4 class extend JPanel, and do drawing in its paintComponent method.

    So, change this:

    public U4() {
        setBackground(Color.white);
    }
    
    
    // ...
    
    public void paint(Graphics g) {
        addMouseListener(this);
        g.setColor(Color.blue);
        g.drawLine(x1, y1, x2, y2);
    } 
    

    to this:

    public U4() {
        setBackground(Color.white);
        addMouseListener(this);
    }
    
    
    // ...
    
    public void paint(Graphics g) {
        //  addMouseListener(this);
        super.paint(g); 
        g.setColor(Color.blue);
        g.drawLine(x1, y1, x2, y2);
    } 
    

    and then next, make the changes that I recommended

    something like:

    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.Stroke;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    
    import javax.swing.*;
    
    public class U4b extends JPanel {
       private static final Color BG = Color.white;
       private static final Color DRAW_COLOR = Color.red;
       private static final int PREF_W = 800;
       private static final int PREF_H = 600;
       private static final Stroke BASIC_STROKE = new BasicStroke(3f);
       private int counter = 0;
       private int x1 = 0;
       private int y1 = 0;
       private int x2 = 0;
       private int y2 = 0;
    
       public U4b() {
          setBackground(BG);
          MyMouseListener myMouseListener = new MyMouseListener();
          addMouseListener(myMouseListener);
          addMouseMotionListener(myMouseListener);
       }
    
       @Override
       public Dimension getPreferredSize() {
          if (isPreferredSizeSet()) {
             return super.getPreferredSize();
          }
          return new Dimension(PREF_W, PREF_H);
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g;
          g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
          g2.setColor(DRAW_COLOR);
          g2.setStroke(BASIC_STROKE);
          g2.drawLine(x1, y1, x2, y2);
       }
    
       private class MyMouseListener extends MouseAdapter {
          @Override
          public void mousePressed(MouseEvent e) {
             counter++;
             System.out.println("Counter: " + counter);
             x1 = e.getX();
             y1 = e.getY();
             x2 = x1;
             y2 = y1;
          }
    
          @Override
          public void mouseDragged(MouseEvent e) {
             x2 = e.getX();
             y2 = e.getY();
             repaint();
          }
    
          @Override
          public void mouseReleased(MouseEvent e) {
             x2 = e.getX();
             y2 = e.getY();
             repaint();
          }
    
       }
    
       private static void createAndShowGui() {
          U4b mainPanel = new U4b();
    
          JFrame frame = new JFrame("U4b");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }