How to change the dimension of a component in a JFrame

后端 未结 3 1833
一个人的身影
一个人的身影 2020-12-20 01:28

Suppose I have a JPanel in a JFrame. When I invoke a method that changes the preferred size of that JPanel, it does not change.

The code looks something like this:

相关标签:
3条回答
  • 2020-12-20 01:48

    +1 to all.

    I usually use a combination of:

    revalidate() and pack(). (see @GagandeepBali and @StanislavL answer here for more reasoning as to my choice of revalidate()) as for pack() this allows for my JFrame to be sized to fit the contents.

    • do not call setPreferredSize rather override getPreferredSize of JPanel.

    • also do not call setSize(..) on JFrame use correct LayoutManager which adjusts to all added components size and than simply call pack() before setting JFrame visible.

    • And lastly but not stressed enough warp creation and manipulation of Swing components in SwingUtilities.invokeXXX block / Event Dispatch Thread

    Here is an example I made:

    Basically a JPanel which overrides getPreferredSize and has a method setPanelSize(int w,int h) which changes variables in JPanel instance to return new Dimensions for getPreferredSize. after that I call revalidate() and pack() on JFrame to refelect changes:

    pic 1

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class Test {
    
        public Test() {
            initComponents();
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new Test();
                }
            });
        }
    
        private void initComponents() {
            final JFrame frame = new JFrame();
            frame.setTitle("Test");
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            final MyPanel myPanel = new MyPanel();
            final JButton changeSizeButton = new JButton("Change size to 300x300");
    
            changeSizeButton.addActionListener(new ActionListener() {
                boolean resized = false;
    
                @Override
                public void actionPerformed(ActionEvent ae) {
                    if (resized) {
                        myPanel.setPanelSize(200, 200);
                        resized = false;
                        changeSizeButton.setText("Change size to 300x300");
                    } else {
                        myPanel.setPanelSize(300, 300);
                        resized = true;
                        changeSizeButton.setText("Change size to 200x200");
                    }
    
                    frame.revalidate();
                    frame.pack();
    
                }
            });
            frame.add(myPanel);
            frame.add(changeSizeButton, BorderLayout.SOUTH);
    
            frame.pack();
            frame.setVisible(true);
        }
    }
    
    class MyPanel extends JPanel {
    
        private int width, height;
    
        public MyPanel() {
            super(true);
            width = 200;
            height = 200;
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(width, height);
        }
    
        public void setPanelSize(int width, int height) {
            this.width = width;
            this.height = height;
        }
    }
    
    0 讨论(0)
  • 2020-12-20 01:54

    You need to invalidate the container hierarchy to make it re-layout the components.

    Simply call invalidate followed by revalidate on the component you have changed.

    Here's a small example...

    public class TestComponentHierarcy {
    
        public static void main(String[] args) {
            new TestComponentHierarcy();
        }
    
        public TestComponentHierarcy() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException ex) {
                    } catch (InstantiationException ex) {
                    } catch (IllegalAccessException ex) {
                    } catch (UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Test");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new GridBagLayout());
                    frame.add(new Test());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class Test extends JPanel {
    
            private Dimension size = new Dimension(10, 10);
    
            public Test() {
    
                setLayout(new GridBagLayout());
                addMouseListener(new MouseAdapter() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                        size.width += 10;
                        size.height += 10;
                        invalidate();
                        revalidate();
                    }
                });
    
            }
    
            @Override
            public Dimension getPreferredSize() {
                return size;
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.RED);
                g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
            }
    
        }
    
    }
    
    0 讨论(0)
  • 2020-12-20 02:03

    Add frame.pack(); after somePanel.expand(); in your main() method. It will be done.

    0 讨论(0)
提交回复
热议问题