JPanel 组件在尝试刷新后消失
JPanel components disappear after trying to refresh them
我正在努力使框架中有两个面板。一个显示 4 张卡片,另一个显示一个按钮。单击该按钮时,将再次随机选择四张牌。当我初始化程序或单击刷新时,卡片没有显示。
谁能解释我做错了什么以及我需要做什么来解决这个问题?
这是我的代码
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class MyFrame extends JFrame{
public MyFrame(){
super("Random Cards");
CardPanel cardPanel = new CardPanel();
JPanel buttonPanel = new JPanel();
JButton jbtRefresh = new JButton("Refresh");
buttonPanel.add(jbtRefresh);
add(cardPanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
jbtRefresh.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
cardPanel.refresh();
}
});
}
public static void main(String[] args){
MyFrame f = new MyFrame();
f.setDefaultCloseOperation(MyFrame.EXIT_ON_CLOSE);
f.setSize(500, 300);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public class CardPanel extends JPanel{
JLabel l1;
JLabel l2;
JLabel l3;
JLabel l4;
void CardPanel(){
refresh();
}
void refresh(){
l1 = new JLabel(new ImageIcon("image/card/" + (int)(1 + Math.random() * 54) + ".png"));
l2 = new JLabel(new ImageIcon("image/card/" + (int)(1 + Math.random() * 54) + ".png"));
l3 = new JLabel(new ImageIcon("image/card/" + (int)(1 + Math.random() * 54) + ".png"));
l4 = new JLabel(new ImageIcon("image/card/" + (int)(1 + Math.random() * 54) + ".png"));
removeAll();
add(l1);
add(l2);
add(l3);
add(l4);
repaint();
}
}
}
简答
调用refresh
时在repaint
之前调用revalidate
...
更长、更合适的答案
考虑改用 CardLayout
。有关详细信息,请参阅 How to Use CardLayout
还有...
- 确保您是 creating/modifying 您 UI 仅来自事件调度线程的上下文,有关详细信息,请参阅 Initial Threads。
- 您可以考虑制作一个
Card
class,它从 JPanel
之类的东西延伸而来,它负责显示特定的卡片。这样你就可以简单地计算你需要的随机卡值并不断更新预先存在的实例,而不是每次都创建新实例。通常,它会 运行 更快并且更有效
Nit pick:你应该避免直接从像JFrame
这样的顶级容器扩展你的UI,它们往往会将你锁定在一个单一的用例并使其难以在将来重用或扩展。无论如何,您并没有真正向框架添加任何新功能
我正在努力使框架中有两个面板。一个显示 4 张卡片,另一个显示一个按钮。单击该按钮时,将再次随机选择四张牌。当我初始化程序或单击刷新时,卡片没有显示。 谁能解释我做错了什么以及我需要做什么来解决这个问题?
这是我的代码
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class MyFrame extends JFrame{
public MyFrame(){
super("Random Cards");
CardPanel cardPanel = new CardPanel();
JPanel buttonPanel = new JPanel();
JButton jbtRefresh = new JButton("Refresh");
buttonPanel.add(jbtRefresh);
add(cardPanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
jbtRefresh.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
cardPanel.refresh();
}
});
}
public static void main(String[] args){
MyFrame f = new MyFrame();
f.setDefaultCloseOperation(MyFrame.EXIT_ON_CLOSE);
f.setSize(500, 300);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public class CardPanel extends JPanel{
JLabel l1;
JLabel l2;
JLabel l3;
JLabel l4;
void CardPanel(){
refresh();
}
void refresh(){
l1 = new JLabel(new ImageIcon("image/card/" + (int)(1 + Math.random() * 54) + ".png"));
l2 = new JLabel(new ImageIcon("image/card/" + (int)(1 + Math.random() * 54) + ".png"));
l3 = new JLabel(new ImageIcon("image/card/" + (int)(1 + Math.random() * 54) + ".png"));
l4 = new JLabel(new ImageIcon("image/card/" + (int)(1 + Math.random() * 54) + ".png"));
removeAll();
add(l1);
add(l2);
add(l3);
add(l4);
repaint();
}
}
}
简答
调用refresh
时在repaint
之前调用revalidate
...
更长、更合适的答案
考虑改用 CardLayout
。有关详细信息,请参阅 How to Use CardLayout
还有...
- 确保您是 creating/modifying 您 UI 仅来自事件调度线程的上下文,有关详细信息,请参阅 Initial Threads。
- 您可以考虑制作一个
Card
class,它从JPanel
之类的东西延伸而来,它负责显示特定的卡片。这样你就可以简单地计算你需要的随机卡值并不断更新预先存在的实例,而不是每次都创建新实例。通常,它会 运行 更快并且更有效
Nit pick:你应该避免直接从像JFrame
这样的顶级容器扩展你的UI,它们往往会将你锁定在一个单一的用例并使其难以在将来重用或扩展。无论如何,您并没有真正向框架添加任何新功能