Search code examples
javaswingjframesizewindow-decoration

Java - Set size of decorated JFrame


I've got a problem with the size of a JFrame:

I want to show content in the Jframe. The content will have the size 640 x 480. But I can not use the method JFrame.setSize(640, 480); because I also want to show the decoration of the window. My first thought was: Add a panel with the preferred dimension and than use pack();. But this also doesn't work - I only get a really small window.

I think the solution to my problem could be similar to this:

Here is my code:

import java.awt.Dimension;

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

public class Fenster extends JFrame {

    JPanel panel;
    Dimension dim;

    Fenster(){

        dim = new Dimension(640, 480);

        panel = new JPanel();
        panel.setSize(dim);
        panel.setMinimumSize(dim);
        panel.setMaximumSize(dim);
        panel.setPreferredSize(dim);
        panel.setBounds(0, 0, 640, 480);
        panel.setDoubleBuffered(true);

        JLabel label = new JLabel("bla");
        panel.add(label);

        this.setLayout(null);
        this.getContentPane().add(panel);
        this.setLocationRelativeTo(null);
        this.setResizable(false);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        this.pack();
        this.setVisible(true);

    }


}

Solution

  • this.setLayout(null); is your problem. Let the layout manager do it's job

    From the JavaDocs

    public void pack()

    Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. The resulting width and height of the window are automatically enlarged if either of dimensions is less than the minimum size as specified by the previous call to the setMinimumSize method.

    If the window and/or its owner are not displayable yet, both of them are made displayable before calculating the preferred size. The Window is validated after its size is being calculated.

    Most containers (JComponent, JPanel) have a default, preferred size of 0x0, the layout manager provides this information based on the requirements of the layout manager itself and the contents of the container, but using a null, you effectivly make the container 0x0...

    No more null layouts

    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.GridBagLayout;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setUndecorated(true);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setLayout(new GridBagLayout());
                add(new JLabel("Look ma, no null layouts!"));
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(640, 480);
            }
    
        }
    
    }
    

    Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify

    See Why is it frowned upon to use a null layout in SWING? for more details...