Search code examples
javaswinglayoutlayout-managerpreferredsize

Java Swing: problems with width


I have problems with understanding the behavior of my application. I want to create a simple window (1000x700px), divided into two parts (250px and 750px width respectively). I tried the following code:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;

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

public class Example extends JFrame
{
    private static final long serialVersionUID = 1L;

    public Example()
    {
        this.setSize(1000, 700);
        this.setTitle("Example");
        this.setResizable(false);
        this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));

        JPanel navigation_panel_wrap = new JPanel();
        JPanel content_panel_wrap = new JPanel();
        navigation_panel_wrap.setPreferredSize(new Dimension(250, 700));
        content_panel_wrap.setPreferredSize(new Dimension(750, 700));
        content_panel_wrap.setBackground(Color.green);
        navigation_panel_wrap.setBackground(Color.red);
        this.getContentPane().add(navigation_panel_wrap);
        this.getContentPane().add(content_panel_wrap);
    }

    public static void main(String[] args)
    {
        Example example = new Example();
        example.setVisible(true);
    }
}

As you can see I manually set layout manager for JFrame (FlowLayout instead of BorderLayout with zero horizontal and vertical gaps). Of course, I can just use BorderLayout and than use add() method with BorderLayout.EAST and BorderLayout.WEST parameters, but I want to understand what's wrong with FlowLayout. When I run my application, I get the following (no green JPanel): enter image description here

If I decrease width of, for example, content_panel_wrap and make it 744px instead of 750px, everything works correctly. enter image description here So the question is - what are these strange 6 pixels? I'm not sure this value is constant for all operating systems, so I want to understand its origin.


Solution

  • As for your codes problem (+1 to @Reimeus) calling pack() is the solution. as per docs:

    Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. If the window and/or its owner are not yet displayable, both are made displayable before calculating the preferred size. The Window will be validated after the preferredSize is calculated.

    Tips:

    • Dont extend JFrame unnecessarily.
    • Use Event Dispatch Thread when creating and changing UI components:

      SwingUtilities.invokeLater(new Runnable() {
          @Override
          public void run() {
            // create UI components etc here
          }
        });
      
    • Dont call setPreferredSize() rather override getPrefferedSize() of component.
    • Dont call setSize(...) on JFrame rather call JFrame#pack() before setting it visible.
    • Dont forget to call JFrame#defaultCloseOperation(..) or your initial/EDT thread will not be terminated when JFrame is closed.

    Here is an example combining my advice and your code:

    enter image description here

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class Example {
    
        private final JFrame frame;
    
        public Example() {
            frame = new JFrame();
            frame.setTitle("Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//app exited when frame closes
            frame.setResizable(false);
            frame.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
    
            JPanel navigation_panel_wrap = new JPanel() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(250, 700);
                }
            };
            JPanel content_panel_wrap = new JPanel() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(750, 700);
                }
            };
    
            content_panel_wrap.setBackground(Color.green);
            navigation_panel_wrap.setBackground(Color.red);
    
            frame.add(navigation_panel_wrap);
            frame.add(content_panel_wrap);
            //pack frame (size components to preferred size)
            frame.pack();
            frame.setVisible(true);//make frame visible
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new Example();
                }
            });
        }
    }