在 Swing 中绘画是一个破坏性的过程。您的组件用于绘制自身的Graphics 上下文是共享资源,即在您的组件之前和之后绘制的组件将使用相同的图形上下文。
这意味着,如果你不清除它,你会看到你之前画过的东西......
在开始绘画之前清除Graphics 上下文是框架的要求...
为此,预计在调用paintComponent 时,您将完全重绘您需要重绘的内容。
看看Performing Custom Painting和Painting in AWT and Swing
你需要停止与这个过程作斗争,开始学习如何使用它——如果你这样做了,你的生活会简单得多;)
更新了一个可能的基本方法的示例
基本上,这只是在组件范围内的某个位置创建一个随机点,将该点添加到 List 并请求重新绘制组件。 paintComponent 方法简单地循环遍历此列表并绘制点,之后它调用 super.paintComponent 来准备 Graphics 用于绘制的上下文...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AutoPaint {
public static void main(String[] args) {
new AutoPaint();
}
public AutoPaint() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Point> points = new ArrayList<>(25);
public TestPane() {
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
points.add(new Point(random(getWidth()), random(getHeight())));
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Point p : points) {
g2d.drawLine(p.x, p.y, p.x, p.y);
}
g2d.dispose();
}
protected int random(int range) {
return (int)Math.round(Math.random() * range);
}
}
}