我有一个自定义的JLayeredPane,我正在游戏循环中重新绘制它。JLayeredPane中添加了两个自定义JPanel。这些是前景和背景JPanel。如何成功地只绘制一次背景JPanel(并在窗口重新调整大小或任何其他原因时重新绘制),以减少对系统资源的影响,同时不断更新前景JPanel。
为了重新迭代,我不想在循环中不断地重新绘制背景JPanel。我只想在必要的时候重新粉刷,因为背景不会改变。并且是大的。
为了做到这一点,我只画了一次背景。然而背景JPanel根本不可见。而前景JPanel正常更新。这几乎就像前景JPanel绘制在背景JPanel的顶部,即使我将两个JPanel都设置为setOpaque(false)
我做了一个mvce,展示了我只画一次背景JPanel,同时不断更新前景JPanel的尝试。
我的代码的问题是后台JPanel没有显示。
现在。我知道,如果我不断地画,它就会显现出来。但这违背了我想要做的事情的目的。我试图只画一次,同时被看到
我的代码只成功地绘制了一次背景JPanel。问题是背景JPanel没有显示。如何解决此问题
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JLayeredPane {
static JFrame frame;
static Main main;
static Dimension screenSize;
public Main() {
JPanel backPanel = new BackPanel();
JPanel frontPanel = new FrontPanel();
add(backPanel, new Integer(7));
add(frontPanel, new Integer(8));
new Thread(() -> {
while (true){
repaint();
}
}).start();
}
public static void main(String[] args) {
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame = new JFrame("Game"); // Just use the constructor
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main = new Main();
frame.add(main, BorderLayout.CENTER);
frame.pack();
frame.setSize(screenSize);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class BackPanel extends JPanel{
public boolean drawn = false;
public BackPanel(){
setVisible(true);
setOpaque(false);
setSize(screenSize);
JLabel test1 = new JLabel("Test1");
JLabel test2 = new JLabel("Test2");
add(test1);
add(test2);
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
drawOnce(g);
}
public void drawOnce(Graphics g){
if (!drawn){
g.setColor(Color.red);
g.fillRect(0, 0, screenSize.width, 200);
drawn=true;
}
}
}
public class FrontPanel extends JPanel{
public FrontPanel(){
setVisible(true);
setOpaque(false);
setSize(screenSize);
JLabel test = new JLabel("Test");
add(test);
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.blue);
g.fillRect(0+screenSize.width/2, 0, screenSize.width/4, 300);
}
}
}
尝试RepaintManager.currentManager(组件).markCompletelyClean(组件)。这将防止部件重新喷漆。您可能需要在每次添加新组件后执行此操作。
http://docs.oracle.com/javase/6/docs/api/javax/swing/RepaintManager.html#markCompletelyClean%28javax.swing.JComponent%29
我不知道这两行代码是否是
super.paintComponent(g);
drawOnce(g);
是问题的根源,我真的不记得paintComponent是如何工作的(测试可能会有所帮助),但试着交换它们:
drawOnce(g);
super.paintComponent(g);
也许,在您的原始版本上,您告诉JVM绘制整个组件,并且只有在AWTEvent添加到队列之后,才能绘制您需要的内容。我想awt的文档会对此进行解释。