具有多层的 JFrame

发布于 2024-08-29 14:01:06 字数 972 浏览 11 评论 0原文

我有一个有两层的窗口:静态背景和包含移动对象的前景。我的想法是只绘制一次背景(因为它不会改变),所以我使更改面板透明并将其添加到静态背景之上。这是代码:

public static void main(String[] args) {
    JPanel changingPanel = new JPanel() {

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillRect(100, 100, 100, 100);
        }
    };
    changingPanel.setOpaque(false);

    JPanel staticPanel = new JPanel();
    staticPanel.setBackground(Color.BLUE);
    staticPanel.setLayout(new BorderLayout());
    staticPanel.add(changingPanel);

    JFrame frame = new JFrame();
    frame.add(staticPanel);
    frame.setSize(800, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}

这段代码给了我我想要的正确图像,但是每次我重新绘制 changingPanel 时,staticPanel 也会被重新绘制(这显然是反对的)仅绘制一次静态面板的整个想法)。有人可以告诉我出了什么问题吗?

仅供参考,我正在使用 javax.swing.Timer 每秒重新计算并重新绘制不断变化的面板 24 次。

I have a window that has two layers: a static background and a foreground that contains moving objects. My idea is to draw the background just once (because it's not going to change), so I make the changing panel transparent and add it on top of the static background. Here is the code for this:

public static void main(String[] args) {
    JPanel changingPanel = new JPanel() {

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillRect(100, 100, 100, 100);
        }
    };
    changingPanel.setOpaque(false);

    JPanel staticPanel = new JPanel();
    staticPanel.setBackground(Color.BLUE);
    staticPanel.setLayout(new BorderLayout());
    staticPanel.add(changingPanel);

    JFrame frame = new JFrame();
    frame.add(staticPanel);
    frame.setSize(800, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}

This piece of code gives me the correct image I want, but every time I repaint changingPanel, staticPanel gets repainted as well (which is obviously against the whole idea of painting the static panel just once). Can somebody show me what's wrong?

FYI I am using the javax.swing.Timer to recalculate and repaint the changing panel 24 times every second.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

水中月 2024-09-05 14:01:06

当您在另一个透明组件之上重新绘制透明组件时,您仍然会“弄脏”下部组件,从而导致它被重新绘制。如果您没有重新绘制下层,则会在其顶部得到图像的涂抹效果。

这里唯一可用的优化是不重新生成较低级别上使用的图像。每次上面的图层发生变化时,仍然需要将光栅绘制到图形缓冲区。

When you repaint a transparent component above another, you still 'dirty' the lower component, causing it the be repainted. If you didn't repaint the lower layer, you would get a smearing effect of the image on top of it.

The only optimisation available here is not regenerating the image used on the lower level. The raster still needs to be painted to the graphics buffer every time the layer above changes.

浅暮の光 2024-09-05 14:01:06

这正是绘画的工作原理。 Swing 必须搜索第一个具有非不透明背景的组件。然后它绘制该组件和子组件,以确保所有绘制都正确完成。

即使您有一个移动组件,SWing 仍然需要“清除”组件的最后位置,这意味着在重新绘制移动的组件之前,它至少必须重新绘制背景面板的该区域。

为了使绘画更有效率,子面板应该是不透明的。我不知道你为什么改变默认设置。

This is exactly the way painting works. Swing has to search for the first component that has a non-opaque background. Then it paints that component and the children to make sure all the painting is done correctly.

Even if you have a moving compnent, SWing would still need to "clear" the last position of the compnent, which means it has to at least repaint that area of the background panel, before repaint the component that moved.

To make the painting more efficient the child panel should be opaque. I don't know why you changed the default setting.

半山落雨半山空 2024-09-05 14:01:06

一个非常简单的方法是使用 jxlayer。实现 AbstractLayerUI 并将其添加到您的组件上。请参阅此处开始使用。

A really easy way is to use jxlayer. Implement AbstractLayerUI and add that over your component. See here to get started.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文