为什么这个 JPanel 不可见?
Why is this JPanel not visible?
我有一个风俗JPanel
,在另一个风俗JPanel
后面,在一个JLayeredPane
。我只想绘制背景 JPanel
一次。因为它不会改变。这将节省系统资源。我如何成功地做到这一点?
我知道如果我允许重复绘制背景 JPanel 就像前景 JPanel 一样,它会被看到。但这无视我的目标。即只画一次
重新迭代。如何绘制一次背景 JPanel,并递归绘制前景 JPanel,同时在 JLayeredPane 中看到两个 JPanel,其中背景 JPanel 在前景 JPanel 后面
这是我目前的尝试。这是行不通的。这段代码的问题是背景 JPanel
根本不可见`
这个问题不是重复的,因为人们正在解决不相关的问题。我现在已经让这个问题解决了我想要解决的问题。如果它可以帮助您解决我的问题。那么问题的 link 就在这里。 question。
这个问题也有一个糟糕的、毫无意义的答案。我什至仍然尝试并完成了工作。
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();
RepaintManager.currentManager(backPanel).markCompletelyClean(backPanel);
}
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){
if (!drawn){
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, screenSize.width, 200);
System.out.println("Reccursion");
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);
}
}
}
首先是一些一般性的评论。你不应该:
- 扩展 JLayeredPane。
- 使用静态变量
- 使用 while true 循环
这是否是 MCVE 并不重要。 MCVE 应该使用正确的结构,否则我们可能会认为您在实际代码中犯了上述错误。
在你的 while 循环中你使用:
repaint();
好吧,您的代码扩展了 JLayeredPane,所以分层窗格的所有层都被绘制了。
如果您只想重绘一个面板,则仅在该面板上调用 repaint()。然而,这可能会导致问题,因为您需要确保在对背景进行任何绘画之前清除背景,这就是背景也需要绘画的原因。
如果您不想重新绘制整个背景,那么您需要具体说明哪些区域需要重新绘制。查看 Custom Painting 上的 Swing 教程中的部分,其中显示了如何优化绘制的内容。请注意 moveSquare(...)
方法如何在两个不同区域调用 repaint() 两次。这将导致重新绘制较小的背景区域。
我有一个风俗JPanel
,在另一个风俗JPanel
后面,在一个JLayeredPane
。我只想绘制背景 JPanel
一次。因为它不会改变。这将节省系统资源。我如何成功地做到这一点?
我知道如果我允许重复绘制背景 JPanel 就像前景 JPanel 一样,它会被看到。但这无视我的目标。即只画一次
重新迭代。如何绘制一次背景 JPanel,并递归绘制前景 JPanel,同时在 JLayeredPane 中看到两个 JPanel,其中背景 JPanel 在前景 JPanel 后面
这是我目前的尝试。这是行不通的。这段代码的问题是背景 JPanel
根本不可见`
这个问题不是重复的,因为人们正在解决不相关的问题。我现在已经让这个问题解决了我想要解决的问题。如果它可以帮助您解决我的问题。那么问题的 link 就在这里。 question。 这个问题也有一个糟糕的、毫无意义的答案。我什至仍然尝试并完成了工作。
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();
RepaintManager.currentManager(backPanel).markCompletelyClean(backPanel);
}
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){
if (!drawn){
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, screenSize.width, 200);
System.out.println("Reccursion");
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);
}
}
}
首先是一些一般性的评论。你不应该:
- 扩展 JLayeredPane。
- 使用静态变量
- 使用 while true 循环
这是否是 MCVE 并不重要。 MCVE 应该使用正确的结构,否则我们可能会认为您在实际代码中犯了上述错误。
在你的 while 循环中你使用:
repaint();
好吧,您的代码扩展了 JLayeredPane,所以分层窗格的所有层都被绘制了。
如果您只想重绘一个面板,则仅在该面板上调用 repaint()。然而,这可能会导致问题,因为您需要确保在对背景进行任何绘画之前清除背景,这就是背景也需要绘画的原因。
如果您不想重新绘制整个背景,那么您需要具体说明哪些区域需要重新绘制。查看 Custom Painting 上的 Swing 教程中的部分,其中显示了如何优化绘制的内容。请注意 moveSquare(...)
方法如何在两个不同区域调用 repaint() 两次。这将导致重新绘制较小的背景区域。