我有一个名为 BigPanel 的 JPanel 子类作为 JFrame 的内容 Pane ,BigPanel 对象内有一个嵌套的 JPanel 子类。单击按钮时,嵌套面板应从一个 JPanel 子类更改为另一个 JPanel 子类。嵌套面板不会重置,正确的子类将打印到控制台,但实际面板不会更新 包 com.grantbroadwater;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class BigPanel extends JPanel {
private static final long serialVersionUID = 1L;
public static final int DIM = GUIFrame.DIM;
private JPanel pnl1;
public BigPanel() {
super(null);
setSize(new Dimension(DIM, DIM));
setBackground(Color.WHITE);
JLabel lbl = new JLabel("Big Panel");
lbl.setBounds(20, 20, 100, 20);
add(lbl);
JButton btn = new JButton("Change");
btn.setBounds(140, 20, 100, 20);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(pnl1 instanceof SubPanelOne){
update(new SubPanelTwo());
}else if(pnl1 instanceof SubPanelTwo){
update(new SubPanelOne());
}
}
});
add(btn);
pnl1 = new SubPanelOne();
pnl1.setLocation(20, 100);
add(pnl1);
}
private void update(JPanel pnl){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.out.print("Pnl1 is of type "+pnl1.getClass());
pnl1 = pnl;
revalidate();
repaint();
pnl1.revalidate();
pnl1.repaint();
System.out.println(" changing to " + pnl1.getClass());
}
});
}
}
最佳答案
- 避免使用
null
布局,像素完美布局是现代 UI 设计中的一种幻觉。影响组件个体尺寸的因素太多,您无法控制其中任何一个。 Swing 的设计目的是与核心的布局管理器一起工作,放弃这些将导致无休止的问题和问题,您将花费越来越多的时间来尝试纠正 - 使用
CardLayout
来实现您想要做的事情,这就是它的设计目的。请参阅How to Use CardLayout了解更多详情
核心问题似乎是缺乏对变量引用如何工作的理解......
pnl1 = pnl;
revalidate();
repaint();
pnl1.revalidate();
pnl1.repaint();
所有这一切都会将内存中的 pnl1
所指向的内容更改为 pnl
在内存中所指向的内容。它不会影响屏幕上的任何内容。您实际上必须删除 pnl1
并添加 pnl
才能发生任何更改。
由于放弃布局管理器,这会增加复杂性,因为每次尝试切换每个组件时都需要更新它们的大小和位置。
invalidate
、revalidate
和 validate
都与布局管理 API 相关。如果您选择忽略它们,它们确实没有什么意义。
关于java - JPanel 不会重新验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29313868/