如何在不清除窗口的情况下重绘Swing? [重复]

问题描述 投票:0回答:2

这个问题在这里已有答案:

我正在实现一个简单的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有一个入口点的应用程序。同时启动一个计时器,以便每秒调用repaint上的Canvas以强制绘制另一个圆圈。

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

java swing draw
2个回答
1
投票

Swing中的绘画具有破坏性。这是一个预期的要求,每次涂装一个部件时,它都会从头开始涂漆。

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

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

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

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

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


0
投票

考虑调用重绘的替代构造函数(...)

重绘(long tm,int x,int y,int width,int height)

这允许您设置要重新绘制的指定区域。

您还可以将您绘制的内容存储在列表中,然后在调用重绘后将绘图重新打印到画布。

© www.soinside.com 2019 - 2024. All rights reserved.