Change Panel size on button click
Asked Answered
A

3

5

I have the following code:

package in.res.num.tapb.ui;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

class MainClass extends JPanel {
    public MainClass() {
        Registration registration = new Registration();
        ButtonPanel buttonPanel = new ButtonPanel();
        buttonPanel.setRegistration(registration);

        buttonPanel.setBorder(BorderFactory.createTitledBorder("Button Panel"));
        registration.setBorder(BorderFactory.createTitledBorder("Registration Panel"));

        setLayout(new BorderLayout());
        add(registration, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);
    }

    private static void createAndShowUI() {
        JFrame frame = new JFrame("Registration");
        frame.getContentPane().add(new MainClass());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }

    @SuppressWarnings("serial")
    private class ButtonPanel extends JPanel {
        private Registration registration;

        public ButtonPanel() {
            setLayout(new GridLayout(1, 0, 10, 0));     
            for (final String keyText : Registration.KEY_TEXTS) {
                JButton btn = new JButton(keyText);
                btn.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        if (registration != null) {
                            registration.swapView(keyText);
                        }
                    }
                });
                add(btn);
            }
        }

        public void setRegistration(Registration registration) {
            this.registration = registration;
        }
    }

    private static class Registration extends JPanel {
        private static final Dimension PREF_SIZE = new Dimension(450, 300);
        public static final String USER_AGREEMENT = "User Agreement";
        public static final String USER_INFO = "User Information";
        public static final String ENROLLMENT = "Enrollment";
        public static final String[] KEY_TEXTS = { USER_AGREEMENT, USER_INFO, ENROLLMENT };
        private CardLayout cardlayout = new CardLayout();
        private JPanel cards = new JPanel(cardlayout);

        public Registration() {
            cards.add(createUserAgreePanel(), USER_AGREEMENT);
            cards.add(createUserInfoPanel(), USER_INFO);
            cards.add(createEnrollmentPanel(), ENROLLMENT);
            setLayout(new BorderLayout());
            add(cards, BorderLayout.CENTER);
        }



        private JPanel createEnrollmentPanel() {
            JPanel enrol = new JPanel();
            enrol.setSize(new Dimension(400, 200));
            enrol.add(new JLabel("Enrollment"));
            return enrol;
        }

        private JPanel createUserAgreePanel() {
            JPanel userAgree = new JPanel();
            userAgree.setSize(new Dimension(200, 300));
            userAgree.add(new JLabel("User Agreement"));
            return userAgree;
        }

        private JPanel createUserInfoPanel() {
            JPanel userInfo = new JPanel();
            userInfo.setSize(new Dimension(300, 400));
            userInfo.add(new JLabel("User Information"));
            return userInfo;
        }

        public void swapView(String key) {
            cardlayout.show(cards, key);
        }

    }

}

As you can see I want to change the size on button click. Is it possible? The above code is not working, I mean the size is not changing. How can I change the size on fly?

Thanks and regards. Edit:

swap the panel on selecting a row of JList.

    getChoicesList().addListSelectionListener(new ListSelectionListener() {

        @Override
        public void valueChanged(ListSelectionEvent listSelectionEvent) {
            getViewPanel().changeView(getChoicesList().getSelectedIndex());
            getChoicePanel().changeView(Constants.PanelInfo.valueOf(getEngine().getChoiceList().get(getChoicesList().getSelectedIndex()).getEnumName()).getDimensionForScrollPaneOfChoicePanel());
            ((MainFrame) getTopLevelAncestor()).pack();
        }
    });

ViewPanel#changeView(), this swaps the panel:

public void changeView(int index) {
    removeAll();
    getPanels().get(index).setPreferredSize(Constants.PanelInfo.valueOf(getEngine().getChoiceList().get(index).getEnumName()).getDimensionForViewPanel());
    add(getPanels().get(index));
}
Afterlife answered 14/8, 2011 at 19:47 Comment(9)
may be this can help #3889998Alloy
+1 for sscce.Saideman
@Tapas Bose, I gave you the answer 4 hours before the answer you accepted. I took the time to explain the problem and explain the solution with a few demo lines of code. What is wrong with my answer? Or do you expect people to write the code for you every time?Cotangent
@Cotangent I believe that's because trashgod posted a complete exampleDistant
@Eng, that is my point. There should be no need to post a complete example. An explanation was given with a solution. People learn by trying and problem solving on their own and should NOT expect us to write the code for them. Posting working code doesn't explain what the original problem is and it doesn't highlight the actual solution. Is the forum about answering a question or is it a competition about who can post the best working code?Cotangent
@camickr, by the rule of stackoverflow we, the users can only accept only one answer atmost and if there was no such rule, your answer would be accepted as well, it is equally helpful. So I gave you up-vote. I have multiple panel to swap not on button click but on selection change of a JList so for that it will be expensive to remember the previously swapped panel, and the structure will not support the reimplementation of its base also I didn't post the actual code, if I did, I would have to post atleast 10 java code so I made a small prototype of same need. I post the main snippet in edit.Afterlife
No one can learn programming unless he/she write his/her own code. :) and I am not in a situation/stage where I need other people to write all the code.Afterlife
@Tapas, the diferrence in the "posted code" was he using removeAll() and I used remvoe(). So even though I spend all the time explaining the two problems you had with your code was wasted. You couldn't even to a little thinking to use the removeAll() method on your own? That is the problem I have with spoon fee code people just look at the code and don't look at the explanation and then do the tinkning on their. And you still haven't looke at your previous question where I gave you a much simpler solution. Good luck with future questions.Cotangent
@Cotangent "So even though I spend all the time explaining the two problems you had with your code was wasted." this hurt me a lot as this is not the fact. :(Afterlife
C
3

You should never use setSize() when using a layout manager. It is the job of the layout manager to determine the size. You can provide hints to the layout manager by setting the peferred or minimum or maximum sizes. However it is not recommend that you do this since components and panels should be displayed at their preferred size which will be determined by the layout manager you are using. If you did override the size then the code should be:

// enrol.setSize(new Dimension(400, 200));
enrol.setPreferredSize(new Dimension(400, 200));

However, this still won't work the way you want because the job of the CardLayout is to determine the largest size of all panels added to the panel using a CardLayout. So when you swap from panel to panel you don't get the size of each individual panel. This is s better experience for the user because the user doesn't want to see the frame size keep changing every time they hit a button.

If you did want to have the frame change size every time you click on a button then the basic code would be:

mainPanel.remove(oldPanel);
mainPanel.add(newPanel);
frame.pack();

Then the layout manager of the main panel will observe the preferred size of the newlay added panel.

Cotangent answered 15/8, 2011 at 0:28 Comment(0)
D
4

After resizing the JFrame, use: yourframe.validate();

Distant answered 14/8, 2011 at 20:35 Comment(1)
Resizing the frame will cause the frame to be validated.Cotangent
C
3

You should never use setSize() when using a layout manager. It is the job of the layout manager to determine the size. You can provide hints to the layout manager by setting the peferred or minimum or maximum sizes. However it is not recommend that you do this since components and panels should be displayed at their preferred size which will be determined by the layout manager you are using. If you did override the size then the code should be:

// enrol.setSize(new Dimension(400, 200));
enrol.setPreferredSize(new Dimension(400, 200));

However, this still won't work the way you want because the job of the CardLayout is to determine the largest size of all panels added to the panel using a CardLayout. So when you swap from panel to panel you don't get the size of each individual panel. This is s better experience for the user because the user doesn't want to see the frame size keep changing every time they hit a button.

If you did want to have the frame change size every time you click on a button then the basic code would be:

mainPanel.remove(oldPanel);
mainPanel.add(newPanel);
frame.pack();

Then the layout manager of the main panel will observe the preferred size of the newlay added panel.

Cotangent answered 15/8, 2011 at 0:28 Comment(0)
S
3

As a concrete example of camickr's answer, the program below shows how to rely on the preferred size of components as the frame is resized via pack(). The faux content is a series of labels, but any JComponent will do. As the content is recreated dynamically, it can change according to other conditions in the program.

enter image description here

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/** @see https://stackoverflow.com/questions/7059278 */
class MainPanel extends JPanel {

    private static final String title = "Registration Panel";
    private JFrame frame = new JFrame(title);
    private JPanel registration = new JPanel();

    public MainPanel() {
        this.setLayout(new BorderLayout());
        registration.setBorder(BorderFactory.createTitledBorder(title));
        registration.add(PanelType.USER_AGREEMENT.panel);
        ButtonPanel buttonPanel = new ButtonPanel();
        buttonPanel.setBorder(BorderFactory.createTitledBorder("Button Panel"));
        add(registration, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);
    }

    private void display() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new MainPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new MainPanel().display();
            }
        });
    }

    private class ButtonPanel extends JPanel {

        public ButtonPanel() {
            for (final PanelType panel : PanelType.values()) {
                final JButton button = panel.button;
                this.add(button);
                button.addActionListener(new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        registration.removeAll();
                        registration.add(panel.create());
                        frame.pack();
                        frame.setLocationRelativeTo(null);
                    }
                });
            }
        }
    }

    private enum PanelType {

        USER_AGREEMENT("User Agreement", 2),
        USER_INFO("User Information", 4),
        ENROLLMENT("Enrollment Form", 6);
        private String name;
        private int count;
        private JButton button;
        private JPanel panel;

        private PanelType(String name, int count) {
            this.name = name;
            this.count= count;
            this.button = new JButton(name);
            this.panel = create();
        }

        private JPanel create() {
            this.panel = new JPanel(new GridLayout(0, 1));
            this.panel.add(new JLabel(name));
            this.panel.add(new JLabel(" "));
            for (int i = 0; i < count; i++) {
                this.panel.add(new JLabel("Label " + String.valueOf(i + 1)));
                            }
            return panel;
        }
    }
}
Saideman answered 15/8, 2011 at 4:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.