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(); } }
“查看”我的主应用程序中的问题的屏幕截图
+ @ 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
的工作之一是为绘画准备图形