具有多层的 JFrame
我有一个有两层的窗口:静态背景和包含移动对象的前景。我的想法是只绘制一次背景(因为它不会改变),所以我使更改面板透明并将其添加到静态背景之上。这是代码:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您在另一个透明组件之上重新绘制透明组件时,您仍然会“弄脏”下部组件,从而导致它被重新绘制。如果您没有重新绘制下层,则会在其顶部得到图像的涂抹效果。
这里唯一可用的优化是不重新生成较低级别上使用的图像。每次上面的图层发生变化时,仍然需要将光栅绘制到图形缓冲区。
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.
这正是绘画的工作原理。 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.
一个非常简单的方法是使用 jxlayer。实现 AbstractLayerUI 并将其添加到您的组件上。请参阅此处开始使用。
A really easy way is to use jxlayer. Implement AbstractLayerUI and add that over your component. See here to get started.