BrainWorx
BrainWorx

Reputation: 103

Updating JPanel from external class will just add another one but dont replace it

My main Java program (MyFrame) should update an existing ContentPanel in its JFrame with an other JPanel initiated by an other class (MyPanel) depending on what JMenuItem is clicked and a parameter for the new JPanel will be passed. When I click the JMenuItem, the JPanel dont update, it is behind the first one and not in foreground until I resize the window. Please can you help me solve this?

import javax.swing.*;
import java.awt.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

public class MyFrame extends JFrame { 

private Container contentContainer;

    public static void main(String[] args) {

        new MyFrame();

    }

    public MyFrame() {

        setTitle("MyFrame");
        setSize(300, 200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setJMenuBar(createMenu());

        MyPanel panel = makePanel(new String("Test oO"));

        contentContainer = this.getContentPane();
        setVisible(true);

    }

    public JMenuBar createMenu() {

        JMenuBar menuBar = new JMenuBar();

        JMenu menu = new JMenu("Menu");       

        JMenuItem menuItem = new JMenuItem("Test");
        menuItem.setMnemonic(KeyEvent.VK_E);
        menuItem.setToolTipText("Test");

        menuItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {                

                MyPanel dynamicPanel = makePanel(new String("Test"));
                contentContainer.add(dynamicPanel);
                contentContainer.revalidate(); 
                contentContainer.repaint();

            }

        });

        menu.add(menuItem);

        JMenuItem menuItem1 = new JMenuItem("Test 1");
        menuItem1.setMnemonic(KeyEvent.VK_E);
        menuItem1.setToolTipText("Test 1");

        menuItem1.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {

                MyPanel dynamicPanel1 = makePanel(new String("Test 1"));
                contentContainer.add(dynamicPanel1);
                revalidate(); 
                repaint();

            }

        });

        menu.add(menuItem1);


        JMenuItem menuItem2 = new JMenuItem("Dialog");
        menuItem2.setMnemonic(KeyEvent.VK_E);
        menuItem2.setToolTipText("Dialog");

        menuItem2.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {

                makeDialog(new String("Zur Info"), new String("Du hast Edit geklickt"));

            }

        });

        menu.add(menuItem2);


        menuBar.add(menu);

        return menuBar;

    }

    public JDialog makeDialog(String title, String content) {

        JDialog meinJDialog = new JDialog();
        meinJDialog.setTitle(title);
        JTextArea contentArea = new JTextArea(content);
        contentArea.setEditable(false);
        meinJDialog.add(contentArea);
        meinJDialog.setSize(200,200);
        meinJDialog.setModal(true);
        meinJDialog.setLocationRelativeTo(null);
        meinJDialog.setVisible(true);
        return meinJDialog;   

    }  

    public MyPanel makePanel(String config) {

        MyPanel panel = new MyPanel(config);
        panel.revalidate(); 
        panel.repaint();
        return panel;

    }  

}

class MyPanel extends JPanel {

    public MyPanel(String config) {

        JButton testButton = new JButton(config);
        add(testButton);
        setVisible(true);
        revalidate(); 
        repaint();
        return;

    }

}

Upvotes: 0

Views: 430

Answers (1)

Robin
Robin

Reputation: 36601

When I add removeAll calls, it seems to work.

import javax.swing.*;
import java.awt.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MyFrame extends JFrame {

  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        new MyFrame();
      }
    });
  }

  private final Container contentContainer;

  public MyFrame() {

    setTitle("MyFrame");
    setSize(300, 200);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    setJMenuBar(createMenu());
    contentContainer = getContentPane();
    contentContainer.add(new MyPanel("Test oO"));

    setVisible(true);
  }

  public JMenuBar createMenu() {

    JMenuBar menuBar = new JMenuBar();

    JMenu menu = new JMenu("Menu");

    JMenuItem menuItem = new JMenuItem("Test");
    menuItem.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        MyPanel dynamicPanel = new MyPanel("Test");
        contentContainer.removeAll();
        contentContainer.add(dynamicPanel);
        contentContainer.revalidate();
        contentContainer.repaint();
      }
    });

    menu.add(menuItem);

    JMenuItem menuItem1 = new JMenuItem("Test 1");
    menuItem1.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        contentContainer.removeAll();
        contentContainer.add(new MyPanel("Test 1"));
        contentContainer.revalidate();
        contentContainer.repaint();
      }
    });
    menu.add(menuItem1);

    menuBar.add(menu);
    return menuBar;
  }

}

class MyPanel extends JPanel {

  public MyPanel(String config) {
    JButton testButton = new JButton(config);
    add(testButton);
    setVisible(true);
    revalidate();
    repaint();
  }
}
  • I also wrapped your main method in an EventQueue.invokeLater call to make sure all Swing operations happen on the EDT
  • I removed all the code related to the dialog, as this was unneeded to demonstrate the problem. Inlined some other methods to reduce the length of the code snippet further

And the golden tip if you need to debug situations like that: press ctrlshiftF1 when your JFrame is focused. This will print out the Swing hierarchy of that component. Doing this with your original code clearly shows that the content pane contains multiple MyPanel instances.

Upvotes: 2

Related Questions