java - 如何在 Swing 中重新绘制而不清除窗口?

标签 java swing draw

我正在实现一个简单的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作为实际窗口:

public class Window extends JFrame {
    public Window(Canvas canvas) {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(canvas);
        pack();
        setVisible(true);
    }
}

还有Controller带有应用程序的入口点。还启动一个计时器,因此 repaintCanvas每秒调用一次以强制绘制另一个圆。

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颜色为白色。

最佳答案

在 Swing 中绘画具有破坏性。每次绘制组件时,都会从头开始绘制,这是一个预期的要求。

您需要定义一个模型来维护从头开始恢复状态所需的信息。

然后,您的绘制例程将迭代此模型并每次绘制元素。

这样做的好处是允许您修改模型、删除或插入元素,从而使您可以简单地更新绘制的内容。

或者,您可以使用“缓冲区”(即 BufferedImage)来完成所有绘制,然后您只需在每次绘制组件时将图像绘制到组件即可。

然而,这意味着您无法撤消或分层绘画,它是直接绘制到图像上的。它还使得调整绘图图像区域的大小变得更加困难,因为您需要手动进行这些更新,而基于“模型”的实现更具适应性

关于java - 如何在 Swing 中重新绘制而不清除窗口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55463856/

相关文章:

java - 在 Lucene 中搜索类似 "UTTD_Equip_City_TE"的单词

java - 如何使 ToggleButton 看起来像 RadioButton 而不改变其行为?

java - Jtable 未填充一条记录

Android WebView 在 scrollTo() 之后损坏绘图

android - 调试绘制和引擎

java - Apache POI 无法检测哈希格式的数字

java - 避免字符串中出现 : and , 的正则表达式模式

Java : JFormattedTextField saving numbers

java - JTable - 拖放

c# - 我可以在按钮内绘制形状吗?