0

I have a panel using a 3x3 GridLayout, which I want to change to a 4x4 layout with the click of a radio button. This is the panel class where I set up my menu and needed buttons. Please keep in mind that this code is a pure draft. I'm just trying to get the main idea to work which is to update the layout using the radio button.

public class MenuChangesLayoutPanel extends JPanel implements ActionListener{

    private JMenuBar menuBar;
    private JMenu menu;
    private JRadioButtonMenuItem r1, r2;
    private ButtonGroup group;
    private JButton [] b;
    public MenuChangesLayoutPanel(){
        setLayout(new GridLayout(0,3));
        setOpaque(true);
        b=new JButton[9];
        for(int i=0; i<9; i++){
            b[i]=new JButton(" ");
            add(b[i]);
        }
        menuBar=new JMenuBar();
        menu=new JMenu("The Menu");
        r1=new JRadioButtonMenuItem("3x3");
        r2=new JRadioButtonMenuItem("4x4");
        group=new ButtonGroup();
        group.add(r1);
        group.add(r2);
        menuBar.add(menu);
        menu.add(r1);
        menu.add(r2);
        r1.setSelected(true);
        r1.addActionListener(this);
        r2.addActionListener(this);
        this.setPreferredSize(new Dimension(500,500));
    }
    public JMenuBar getBar(){
        return menuBar;
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        JButton [] buttons=new JButton[7];
        if(e.getSource()==r2){
            System.out.println("r2 pressed");
            ((GridLayout) this.getLayout()).setRows(4);
            ((GridLayout) this.getLayout()).setRows(4);
            for(int i=0; i<7; i++){
                buttons[i]=new JButton();
                this.add(buttons[i]);
            }
            repaint();
        }
    }
}

The frame class:

public class MenuChangesLayout extends JFrame {
    private static final long serialVersionUID = 1L;
    private MenuChangesLayoutPanel panel;

    public MenuChangesLayout(){
        panel=new MenuChangesLayoutPanel();
        this.setJMenuBar(panel.getBar());

        this.setContentPane(panel);

        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.pack();
        this.setVisible(true);
    }


    public static void main(String[] args) {
        // TODO Auto-generated method stub
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new MenuChangesLayout();
            }
        });
    }
}

When I run the program I get the intended initial effect(a 3x3 grid): enter image description here

but when I press the 4x4 button, no change happens until I re-size the frame manually. Shouldn't this happen automatically since I already called the repaint method in the actionPerformed method? This is the image I see after I re-size manually: enter image description here

Omar Sharaki
  • 360
  • 9
  • 34

2 Answers2

4

No. You have to force JPanel to revalidate components:

this.revalidate();
Branislav Lazic
  • 14,388
  • 8
  • 60
  • 85
  • Is there a difference between using validate() and revalidate()? Also is the this keyword necessary here? – Omar Sharaki Aug 05 '15 at 23:09
  • @OmarSharaki No `this` is not necessary in your case. I used it to explicitly point at current instance of `MenuChangesLayoutPanel` class. For `validate()` and `revalidate()` read [Java docs](http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#revalidate()) – Branislav Lazic Aug 06 '15 at 06:09
3

Add in a validate call to the base panel.

 if(e.getSource()==r2){
        System.out.println("r2 pressed");
        ((GridLayout) this.getLayout()).setRows(4);
        ((GridLayout) this.getLayout()).setRows(4);
        for(int i=0; i<7; i++){
            buttons[i]=new JButton();
            this.add(buttons[i]);
        }

        validate()
        repaint();
    }
andrewdleach
  • 2,458
  • 2
  • 17
  • 25