-1

I've hit a problem in getting a JPanel to update.

My simple program uses a custom JPanel which displays a label and a textfield. A Jbutton on the main panel is used to replace the JPanel with a new JPanel. The initial panel shows up fine but when the button is pressed the panel is not updated with a new MyPanel. I can tell that a new object is being created as count is being incremented.

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);
    }
}

and my custom panel....

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);
    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
Gardener22
  • 11
  • 1

1 Answers1

1

You state:

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

And yet this code:

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

and yet this code does not do this at all. All it does is change the JPanel referenced by the vp variable, but has absolutely no effect on the JPanel that is being displayed by the GUI, which suggests that you're confusing reference variable with reference or object. To change the JPanel that is displayed, you must do exactly this: add the new JPanel into the container JPanel into the BorderLayout.CENTER (default) position, then call revalidate() and repaint() on the container.

e.g.,

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();
    }
});

Or better still -- use a CardLayout to swap views.

Or better still -- simply clear the value held by the JTextField.

For more on the distinction between reference variable and object, please check out Jon Skeet's answer to this question: What is the difference between a variable, object, and reference?

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Thanks, but won't that just add another JPanel to the main panel (mp)? – Gardener22 Aug 03 '19 at 18:02
  • @Gardener22: yes it will, but isn't that what you're trying to do here? Please clarify. – Hovercraft Full Of Eels Aug 03 '19 at 18:03
  • @Gardener22: it will add the new JPanel and cover the previous one, since that is how BorderLayout works. – Hovercraft Full Of Eels Aug 03 '19 at 18:04
  • Thanks for your quick answers @Hovercraft. I'm guessing my problem is mixing objects and references. The code I gave is just an example for a more complex JPanel which can return different views depending on the constuctor but the principle is the same. I thought I could just repoint the initial panel (vp) without removing and replacing. I'll read through the link you provided. – Gardener22 Aug 03 '19 at 18:36
  • @Gardener22: that is the key. The vp variable is a reference variable, just a pointer that points to an object. Simply changing what the pointer is pointing to will have absolutely no effect on objects that it previously pointed to or to the GUI itself. The GUI holds a MyPanel object not the vp variable. – Hovercraft Full Of Eels Aug 03 '19 at 18:38