JPanel 不会更新

JPanel won't update

我在更新 JPanel 时遇到了问题。

我的简单程序使用显示标签和文本字段的自定义 JPanel。主面板上的 Jbutton 用于用新的 JPanel 替换 JPanel。初始面板显示正常,但是当按下按钮时,面板不会更新为新的 MyPanel。我可以看出随着计数的增加正在创建一个新对象。

public class SwingTest extends JFrame{

    private JPanel mp;
    private JPanel vp;
    private JButton button;

    public static void main(String[] args) {
        SwingTest st = new SwingTest();
    }

    public SwingTest() {
        vp = new MyPanel();
        mp = new JPanel(new BorderLayout());
        mp.add(vp, BorderLayout.CENTER);
        button = new JButton("Change");
        button.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent ae) {
                vp = new MyPanel();
                vp.revalidate();
            }
        });

        mp.add(button, BorderLayout.SOUTH);
        this.add(mp);
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        setSize(250, 150);
        pack();
        setVisible(true);
    }
}

和我的自定义面板....

public class MyPanel extends JPanel{

    private JLabel label;
    private JTextField tf;

    static int count = 0;

    public MyPanel(){
        count++;
        setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        setPreferredSize(new Dimension(400, 200));

        c.gridx = 0;
        c.gridy = 0;

        label = new JLabel(String.valueOf(count));
        tf = new JTextField(10);

        add(label,c);
        c.gridx = 1;

        add(tf, c);
    }
}

您说:

A Jbutton on the main panel is used to replace the JPanel with a new JPanel.

还有这段代码:

button.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent ae) {
        vp = new MyPanel();
        vp.revalidate();
    }
});

然而这段代码根本没有这样做。它所做的只是通过 vp 变量更改 JPanel referenced,但对 GUI 显示的 JPanel 绝对没有影响,这表明您正在混淆 引用变量引用或对象。要更改显示的 JPanel,您必须完全按照以下步骤操作:将新的 JPanel 添加到容器 JPanel 到 BorderLayout.CENTER(默认)位置,然后在容器上调用 revalidate()repaint() .

例如,

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent ae) {
        // vp = new MyPanel();
        // vp.revalidate();
        mp.remove(vp);  // remove the original MyPanel from the GUI
        vp = new MyPanel();  // create a new one
        mp.add(vp, BorderLayout.CENTER); // add it to the container

        // ask the container to layout and display the new component 
        mp.revalidate();
        mp.repaint();
    }
});

或者更好——使用 CardLayout 交换视图。

或者更好 - 只需清除 JTextField 持有的值。

更多关于引用变量和对象之间的区别,请查看 Jon Skeet 对这个问题的回答:What is the difference between a variable, object, and reference?