paintComponent draws other components on top of my drawing
graphics2d, java, paintcomponent, repaint, swing
Solution
+1 to @MadProgrammer's answers.
- You should have `super.paintComponent(..)` as the first call in your overriden `paintComponent()`
- Do not extend `JFrame` unnecessarily
- Create and minipulate Swing components via EDT
- Dont call `setPrefferedSize()` rather override `getPrefferedSize()`
Here is an example which incorporates my advice's and @MadProgrammer's:
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
JFrame frame;
public Test() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final PaintPanel paintPanel = new PaintPanel();
paintPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
paintPanel.addRect(e.getX(), e.getY());
}
});
frame.setLayout(new FlowLayout());
frame.add(paintPanel);
frame.add(new JButton("Dummy"));
frame.pack();
frame.setVisible(true);
}
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Test();
}
});
}
}
class PaintPanel extends JPanel {
public PaintPanel() {
addRect(100, 100);
}
ArrayList<Rectangle> rects = new ArrayList<>();
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setPaintMode();
for (Rectangle r : rects) {
g2d.setStroke(new BasicStroke(1));
g2d.fillRect(r.x, r.y, r.width, r.height);
}
}
public void addRect(int x, int y) {
rects.add(new Rectangle(x, y, 10, 10));
repaint();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
}
Problem
I'm trying to build a simple paint tool. The `mouseDrag` events creates a new ellipse and causes my `JPanel` to `repaint()`. This works fine so far. However, if I press any button (or any other UI component) before firing the `mouseDrag` event for the first time, the button is painted in the upper left corner of my panel. I have isolated the code into this test application: ``` import java.awt.BasicStroke; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Test extends JFrame { public Test() { final JPanel paintPanel = new JPanel(){ @Override protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D)g; g2d.setPaintMode(); g2d.setStroke(new BasicStroke(1)); g2d.fillRect(100, 100, 10, 10); } }; paintPanel.setPreferredSize(new Dimension(300,300)); paintPanel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { paintPanel.repaint(); } }); this.setLayout(new FlowLayout()); this.add(paintPanel); this.add(new JButton("Dummy")); this.pack(); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String... args) { new Test(); } } ``` A Screenshot for "seeing" the problem in my Main application