paintComponent在绘图之上绘制其他组件

我正在尝试构建一个简单的绘图工具。 mouseDrag事件创建一个新的椭圆并使我的JPanel repaint()

这到目前为止工作正常。 但是,如果我在第一次触发mouseDrag事件之前按下任何按钮(或任何其他UI组件),则该按钮将绘制在我面板的左上角。

我已将代码隔离到此测试应用程序中:

 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(); } } 

单击Panel之前的TestApp单击Panel后TestApp

“查看”我的主应用程序中的问题的屏幕截图

+ @ MadProgrammer的答案+1。

  • 您应该将super.paintComponent(..)作为覆盖paintComponent()的第一个调用
  • 不要不必要地扩展JFrame
  • 通过EDT创建和修改Swing组件
  • 不要调用setPrefferedSize()而是覆盖getPrefferedSize()

这是一个结合我的建议和@MadProgrammer的例子:

在此处输入图像描述

 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 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(rx, ry, 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); } } 

你不是在调用super.paintComponent

用于绘画循环的图形上下文在开始绘制的所有组件之间共享,这意味着如果在绘制之前没有注意清除它,您将最终得到在您之前绘制的内容。

paintComponent的工作之一是为绘画准备图形