Question

Basically, I have to simply paint the text "Mouse entered at" followed by its coordinates. My code does this successfully when mouseMoved is not implemented. When it is, it never shows that the mouse entered and goes directly to "Mouse moved at". I can understand how the mouseMoved can do this since entering the panel is also moving the mouse at that location. I've tried storing the moves in a vector and displaying them (not necessary for this project, yet), but it still didn't paint that the mouse entered. That makes me suspect there's something deeper causing this. Is there an easy fix?

I apologize for the raw, unfinished code (unfinished in that it doesn't do everything I need it to yet, but it does compile and run with it's GUI counterpart).

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;

public class DrawingArea extends JPanel {

int x1, x2, y1, y2;
int shapeType;
char mouseAction;
Vector<String> eventList = new Vector<String>();

public DrawingArea() {
    initialize();
}

public void initialize() {


    addMouseListener(new MouseAdapter() {

      public void mouseEntered(MouseEvent m) {
          x1 = m.getX();
          y1 = m.getY();
          mouseAction = 'a';
          shapeType = 0;
          repaint();

      }

     public void mouseExited (MouseEvent m) {
         x1 = m.getX();
         y1 = m.getY();
         mouseAction = 'b';
         shapeType = 0;
         repaint();
     }

      public void mousePressed(MouseEvent m) {

          x1 = m.getX();
          y1 = m.getY();
          mouseAction = 'd';
          shapeType = 0;
          repaint();
      }
      public void mouseReleased(MouseEvent m) {

          x2 = m.getX();
          y2 = m.getY();
          repaint();
      }
    });

  addMouseMotionListener(new MouseMotionAdapter() {

      public void mouseMoved (MouseEvent m) {

          x2 = m.getX();
          y2 = m.getY();
          mouseAction = 'c';
          shapeType = 0;
          repaint();
      }

       public void mouseDragged(MouseEvent m) {

             x2 = m.getX();
             y2 = m.getY();
             repaint();
          }
      });
}

public void output(String event, MouseEvent m) {

}

public void setShapeType(int num) {

    if (num == 1) {
        shapeType = 1;
        mouseAction = 'z';
        repaint();
    }
    else if (num == 2) {
        shapeType = 2;
        mouseAction = 'z';
        repaint();
    }
    else if (num == 3) {
        shapeType = 0;
        mouseAction = 'z';
        repaint();
    }
}

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

    if (shapeType == 1) {

        g.drawString("Rectangle", 25,25);

    }
    else if (shapeType == 2)
        g.drawString("Circle", 25, 25);

    if (mouseAction == 'a') {
        g.drawString("Mouse entered at (" + x1+ ", " + y1 + ")", 25, 25);
    }

    else if (mouseAction == 'b') {
        g.drawString("Mouse exited at (" + x1 + ", " + y1 + ")", 25, 25);

    }

    else if (mouseAction == 'c') {
        g.drawString("Mouse moved at (" + x2 + ", " + y2 + ")", 25, 25);

    }

    else if (mouseAction == 'd') 
        g.drawString("Mouse clicked at (" + x1 + ", " + y1 + ")", 25, 25);
}
}

For reference, here is the GUI code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class SimpleGUI extends JFrame {

DrawingArea drawArea = new DrawingArea();


public SimpleGUI() {
    createGUI();
}


public void createGUI() {

    JFrame main = new JFrame();
    main.setVisible(true);
    main.setSize(500, 600);
    main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel right = new JPanel(new GridLayout(20,1));
    JPanel bottom = new JPanel();

    JButton rect = new JButton("Rectangle");
    JButton circ = new JButton("Circle");
    JButton erase = new JButton("Erase");
    JButton send = new JButton("Send");

    JTextField text = new JTextField(30);

    right.add(rect);
    right.add(circ);
    right.add(erase);

    bottom.add(text);
    bottom.add(send);

    drawArea.setBackground(Color.WHITE);

    main.add(drawArea, BorderLayout.CENTER);
    main.add(right, BorderLayout.EAST);
    main.add(bottom, BorderLayout.SOUTH);

    rect.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            drawArea.setShapeType(1);
        }
    });

    circ.addActionListener (new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            drawArea.setShapeType(2);
        }

    });

    erase.addActionListener (new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            drawArea.setShapeType(3);
        }
    });

}




public static void main (String[] args) {

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new SimpleGUI();
        }
    });
}

}
Was it helpful?

Solution

The problem isn't with the listeners, it's with your render logic...

if (mouseAction == 'a') {
    g.drawString("Mouse entered at (" + x1 + ", " + y1 + ")", 25, 25);
} else if (mouseAction == 'b') {
    g.drawString("Mouse exited at (" + x1 + ", " + y1 + ")", 25, 25);
} else if (mouseAction == 'c') {
    g.drawString("Mouse moved at (" + x2 + ", " + y2 + ")", 25, 25);
} else if (mouseAction == 'd') {
    g.drawString("Mouse clicked at (" + x1 + ", " + y1 + ")", 25, 25);
}

Basically, when the mouse enters, it triggers a mouseAction of a, which is immeditly followed by a mouseAction of c.

I would surmise that the repaint manager never gets time to render a because c overrides it.

If you updated your paint code to separate the logic between motion and action you should be able to see the difference.

g.drawString("Mouse " + (mouseEntered ? "entered" : "exited") + " at (" + x1 + ", " + y1 + ")", 25, 50);
if (mouseAction == 'c') {
    g.drawString("Mouse moved at (" + x2 + ", " + y2 + ")", 25, 25);
} else if (mouseAction == 'd') {
    g.drawString("Mouse clicked at (" + x1 + ", " + y1 + ")", 25, 25);
}

I added a mouseEntered field, which is a simple boolean value, set to true from mouseEntered and false from mouseExited

Also, convention prefers overriding the paintComponent method rather the paint. paintComponent is double buffered, paint isn't.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top