Search code examples
javaswinglayout-managercardlayout

Display different panel size in CardLayout


I have a JPanel (cardLayoutPanel) which layout is CardLayout.

I also have another 3 different panels (firstPagePanel, secondPagePanel, thirdPagePanel)

  • firstPagePanel size is approximately around 450x400,
  • secondPagePanel size is approximately around 800x600
  • thirdPagePanel size is approximately around 1024x768

I cardLayoutPanel.add all 3 panels and I show firstPagePanel first as my view.

I want to let my program displayed the size of firstPagePanel first which is 450x400 and then if secondPagePanel is displayed, it will change the size to 800x600 and if thirdPagePanel is displayed,it will change the size to 1024,768

Instead of guessing what my 3 panel size should be, I used frame.getPreferredSize() but my first view will always take in the size of my thirdPagePanel which is 1024x768 instead of 450x400;

What can I do to resolve this issue?

public class MainFrame { 
    private CardLayout cardLayout = new CardLayout();
    private JPanel cardLayoutPanel = new JPanel();
    private FirstPagePanel firstPagePanel = new FirstPagePanel(); 
    private SecondPagePanel secondPagePanel = new SecondPagePanel();    
    private ThirdPagePanel thirdPagePanel = new ThirdPagePanel();
    private JFrame frame = new JFrame("Panel size test");

    public MainFrame() {
        cardLayoutPanel.setLayout(cardLayout);
        cardLayoutPanel.add(firstPagePanel,"1");
        cardLayoutPanel.add(secondPagePanel,"2");
        cardLayoutPanel.add(thirdPagePanel,"3");
        cardLayout.show(cardLayoutPanel,"1");
        frame.add(cardLayoutPanel);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.pack();
        frame.getPreferredSize();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setResizable(false);
    }
}

Solution

  • The easiest way is to:

    • Remove the current panel.
    • Add the new panel.
    • Pack the top level container.

    E.G.

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;
    import javax.swing.*;
    import javax.swing.border.EmptyBorder;
    
    public class ThreeSizeGui {
    
        public static void swapComponentsAndResizeUI(
                JComponent ui, 
                JComponent current,
                JComponent next) {
            ui.remove(current);
            ui.add(next);
            current = next;
            Component c = ui.getTopLevelAncestor();
            if (c instanceof Window) {
                Window w = (Window) c;
                w.pack();
            }
        }
    
        public static void main(String[] args) {
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    final JPanel ui = new JPanel(new BorderLayout(4, 4));
                    ui.setBorder(new EmptyBorder(6, 6, 6, 6));
    
                    JPanel controls = new JPanel(
                            new FlowLayout(FlowLayout.LEADING));
                    ui.add(controls, BorderLayout.PAGE_START);
                    int s = 100;
                    Dimension[] sizes = {
                        new Dimension(s * 4, s * 2),
                        new Dimension(s * 6, s * 3),
                        new Dimension(s * 8, s * 4)
                    };
                    final JComboBox cb = new JComboBox(sizes);
                    controls.add(cb);
                    final JPanel[] panels = new JPanel[sizes.length];
                    for (int ii = 0; ii < sizes.length; ii++) {
                        Dimension d = sizes[ii];
                        BufferedImage bi = new BufferedImage(
                                d.width, d.height, BufferedImage.TYPE_INT_RGB);
                        JPanel p = new JPanel(new GridLayout());
                        JLabel l = new JLabel(new ImageIcon(bi));
                        p.add(l);
                        panels[ii] = p;
                    }
                    ItemListener sizeListener = new ItemListener() {
    
                        JPanel current = panels[0];
    
                        @Override
                        public void itemStateChanged(ItemEvent e) {
                            JPanel next = panels[cb.getSelectedIndex()];
                            swapComponentsAndResizeUI(ui, current, next);
                            current = next;
                        }
                    };
                    cb.addItemListener(sizeListener);
    
                    ui.add(panels[0], BorderLayout.CENTER);
    
                    JFrame f = new JFrame("Three Sized Panels");
                    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    f.setContentPane(ui);
                    f.pack();
                    f.setLocationByPlatform(true);
                    f.setVisible(true);
                }
            };
            SwingUtilities.invokeLater(r);
        }
    }