如何在不清除 window 的情况下在 Swing 中重绘?
How to repaint in Swing without clearing the window?
我正在实现一个简单的 Canvas
,其中可以像现实生活中的人一样用纸和铅笔绘制项目,而无需在每次绘制对象时清除整个页面。
到目前为止我有什么...
一个Canvas
实现绘图:
public class Canvas extends JPanel {
private final Random random = new Random();
public Canvas() {
setOpaque(false); // I thought setting this flag makes the drawn pixels be preserved...
}
@Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(random.nextInt(getWidth()), random.nextInt(getHeight()), 5, 5);
}
}
Window
实际window:
public class Window extends JFrame {
public Window(Canvas canvas) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(canvas);
pack();
setVisible(true);
}
}
并且 Controller
带有应用程序的入口点。还启动一个计时器,以便每秒调用 Canvas
上的 repaint
以强制绘制另一个圆。
public class Controller {
public static void main(String[] args) {
Canvas canvas = new Canvas();
SwingUtilities.invokeLater(() -> new Window(canvas));
new Timer(1000, e -> canvas.repaint()).start();
}
}
问题是每当绘制一个新的圆圈时,之前的圆圈就会被清除。似乎还有一些进程用白色填充 JPanel
或者整个 JFrame
。
考虑调用 repaint(...) 的替代构造函数
repaint(long tm, int x, int y, int width, int height)
这允许您设置要重绘的指定区域。
您也可以只将绘制的内容存储在列表中,然后在调用重绘后将绘图重新打印到 canvas。
Swing 中的绘画具有破坏性。每次绘制组件时,都从头开始绘制,这是预期的要求。
您需要定义一个模型来维护从头开始恢复状态所需的信息。
然后您的绘制例程将迭代此模型并每次绘制元素。
这样做的好处是允许您修改模型、删除或插入元素,这样您就可以简单地更新绘制的内容。
或者,您可以使用一个 "buffer"(即 BufferedImage
),在其上完成所有绘制,然后您只需在每次绘制组件时将图像绘制到组件.
然而,这意味着您无法撤消或分层绘画,它是直接绘制到图像上的。它还使调整绘图图像区域的大小变得更加困难,因为您需要手动进行这些更新,而基于 "model" 的实现更具适应性
我正在实现一个简单的 Canvas
,其中可以像现实生活中的人一样用纸和铅笔绘制项目,而无需在每次绘制对象时清除整个页面。
到目前为止我有什么...
一个Canvas
实现绘图:
public class Canvas extends JPanel {
private final Random random = new Random();
public Canvas() {
setOpaque(false); // I thought setting this flag makes the drawn pixels be preserved...
}
@Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(random.nextInt(getWidth()), random.nextInt(getHeight()), 5, 5);
}
}
Window
实际window:
public class Window extends JFrame {
public Window(Canvas canvas) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(canvas);
pack();
setVisible(true);
}
}
并且 Controller
带有应用程序的入口点。还启动一个计时器,以便每秒调用 Canvas
上的 repaint
以强制绘制另一个圆。
public class Controller {
public static void main(String[] args) {
Canvas canvas = new Canvas();
SwingUtilities.invokeLater(() -> new Window(canvas));
new Timer(1000, e -> canvas.repaint()).start();
}
}
问题是每当绘制一个新的圆圈时,之前的圆圈就会被清除。似乎还有一些进程用白色填充 JPanel
或者整个 JFrame
。
考虑调用 repaint(...) 的替代构造函数
repaint(long tm, int x, int y, int width, int height)
这允许您设置要重绘的指定区域。
您也可以只将绘制的内容存储在列表中,然后在调用重绘后将绘图重新打印到 canvas。
Swing 中的绘画具有破坏性。每次绘制组件时,都从头开始绘制,这是预期的要求。
您需要定义一个模型来维护从头开始恢复状态所需的信息。
然后您的绘制例程将迭代此模型并每次绘制元素。
这样做的好处是允许您修改模型、删除或插入元素,这样您就可以简单地更新绘制的内容。
或者,您可以使用一个 "buffer"(即 BufferedImage
),在其上完成所有绘制,然后您只需在每次绘制组件时将图像绘制到组件.
然而,这意味着您无法撤消或分层绘画,它是直接绘制到图像上的。它还使调整绘图图像区域的大小变得更加困难,因为您需要手动进行这些更新,而基于 "model" 的实现更具适应性