I want to draw ovals while dragging my mouse over a JComponent I added to a JFrame. I created two classes, one which extends JComponent, implements MouseMotionListener and overrides the paint(Graphics g) method, and another class with the main method in which I create a JFrame and add the JComponent to the frame. However, when I click and drag my mouse, nothing happens. I then added a default constructor to my Painter class and addMouseMotionListener(this) and setPreferredSize(new Dimension(800,600));, which made a black oval appear and follow my mouse pointer, deleting the previous ovals.
I have included the code for the two classes. Can anyone guide me on what could be wrong?
When I change JComponent to JPanel it works. Why does it not work this way with JComponent?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JComponent;
public class Painter extends JComponent implements MouseMotionListener {
private int x = -10;
private int y = -10;
public Painter() {
addMouseMotionListener(this);
setPreferredSize(new Dimension(800,600));
}
@Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.black);
g2.fillOval(x, y, 10, 10);
}
@Override
public void mouseDragged(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
@Override
public void mouseMoved(MouseEvent e) {
// do nothing
}
}
import javax.swing.JFrame;
public class Main{
public static void main(String[] args) {
JFrame frame = new JFrame();
Painter painter = new Painter();
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(painter);
frame.setVisible(true);
}
}
Actually it works correctly with JComponent.
The difference between the two components is that by default:
JComponentis non-opaque (transparent), which means the parent component will be painted first before the JComponent painting method is invoked and therefore the background is cleared so you only see a single oval.JPanelis opaque, which means it is responsible for clearing the background first before doing the custom painting to prevent painting artifacts. You are not doing this.What you are seeing is a painting artifact with the JPanel since the old painting is not removed.
Try drawing on the panel and then resize the frame and you will see all the ovals except the last one are removed.
See: https://stackoverflow.com/a/52878359/131872 for one way to do the painting.