具有多个图层的JFrame

时间:2010-04-23 04:50:17

标签: java swing performance jcomponent javax.swing.timer

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

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次。

3 个答案:

答案 0 :(得分:7)

当您将透明组件重新绘制在另一个组件上方时,您仍然会“弄脏”下方组件,从而使其重新绘制。如果您没有重新绘制下层,则会在其上方获得图像的拖尾效果。

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

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:2)

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