嗨我在点击刷新按钮后重绘JPanel有很多麻烦,在我的真实应用程序中我有Jlabels表示模型的文件列表,每次刷新按钮被点击的Jlabels列表Jpanel必须相应地更新,我在做这件事时遇到了很多麻烦,所以在这里我做了一个简单干净且可编译的例子,我希望在点击刷新按钮之后,清理JPanel(只是为了让事情变得简单)。所以我确保在EDT中调用更新,我在chnaged Jpanel(panConf)上手动执行了无效,并且我将revalidate调用到最高的comp,即JFrame。没有任何工作,所以我添加了重绘,它也没有工作。你能帮帮我吗?
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class PanRepaint extends JFrame {
private JPanel pan1;
private JPanel mainPanel;
private JPanel panConf;
private JFrame dis;
public PanRepaint() {
JLabel label1 = new JLabel("ZAZAZA");
JLabel label2 = new JLabel("Label 2");
JButton btn = new JButton("Update");
dis = this;
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
panConf = new JPanel();
panConf.invalidate();
//dis.invalidate();
dis.validate();
dis.repaint();
}
});
}
});
panConf = new JPanel();
pan1 = new JPanel();
mainPanel = new JPanel();
panConf.add(label1);
panConf.add(label2);
pan1.add(btn);
mainPanel.add(panConf);
mainPanel.add(pan1);
setContentPane(mainPanel);
this.setSize(400, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
PanRepaint pr = new PanRepaint();
}
}
答案 0 :(得分:3)
您在ActionListener的actionPerformed方法中创建了一个新的JPanel,但是将其添加到任何内容,特别是您将其添加到容器层次结构通向顶级窗口(此处为您的JFrame)的容器中,因此对它的更改不会是反映在GUI中。
我怀疑你是在谬论下,如果你有一个变量引用一个新对象并改变新对象的状态,这里是panConf,你将以某种方式改变变量先前引用的原始对象的状态,但这不是Java的工作原理。 panConf在程序启动时引用的原始JPanel仍然存在,并且仍然在GUI中保持不变。关键是你必须理解引用变量和对象(或引用)之间的区别。这是一个关键的Java概念,可能需要一些努力来完全获得,但值得付出努力。
而只是删除原始panConf JPanel所持有的组件:
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// do not create a new JPanel here
panConf.removeAll();
panConf.revalidate();
panConf.repaint();
}
});
或者更好的是,使用 CardLayout 来交换视图。
此外,无需在EDT上使用SwingUtilities.invokeLater
和Runnable队列。代码已在事件线程上调用。