skip to Main Content

So I am a computer science student and I’ve finished my first year. I wanted to create a simple program and I realized that I am so tired of using no layout;

this.setLayout(null);

It is so tiresome to add bounds to every single component. Well, I have been using JPanel components and GridLayout a lot, which have made my work a bit easier. But I am tired of it.

I care very much about the look of the GUI I make and use almost half the time programming to make the GUI look good before I start adding the functionality of the code. By not using a layout and adding bounds I am forced to setResizable(false) because it looks bad if I change the size of the JFrame.

I’ve been searching a bit, and I know of BorderLayout, and FlowLayout, but I don’t like them. Is there any Layout that keeps the relative size of the components with respect to the size of the window?

For example I want to make a simple program that looks like this: (Quick sketch in Photoshop)

enter image description here

I can easily make this with 3 panels, but as I said, if I change the size of the frame everything stays in place instead of being relative to the window-size.

Can you guys help me?

5

Answers


  1. This design looks for me to fit the BorderLayout, where in the NORTH you have the values that changes the CENTER you have the main part, and the SOUTH you have the buttons.

    Link to the Oracle Border Layout

    You can apply this BorderLayout to the JFrame, then create 3 JPanels for each of the NORTH,CENTER and SOUTH sections. If you want to use responsive design for the components and panels, take a look at GridBagLayout which is much more flexible than the GridLayout

    Login or Signup to reply.
  2. Try GridBagLayout.

    Your sketch is actually quite close to the one of the examples in the official tutorial.

    Login or Signup to reply.
  3. Layout management is a very complex problem, I don’t think people really appreciate just how complex it really is.

    No one layout is ever going to achieve everything your want, in most cases, you will need to resort to two or more layouts, especially as your requirements become more complex.

    For example, the following is simply a BorderLayout at the base and the buttons on a JPanel using a FlowLayout

    LayoutLayout

    Which is achieved by using

    JList listOfThings = new JList(...);
    JTextField tf = new JTextField();
    
    JButton add = new JButton("Add");
    JButton delete = new JButton("Delete");
    JButton go = new JButton("Go...");
    
    JPanel buttons = new JPanel();
    buttons.add(add);
    buttons.add(delete);
    buttons.add(go);
    
    add(new BorderLayout());
    add(tf, BorderLayout.NORTH);
    add(new JScrollPane(listOfThings));
    add(buttons, BorderLayout.SOUTH);
    

    For more complex layouts, I would consider using something like GridBagLayout. You may also want to consider MigLayout as an alternative

    Take a look at Laying Out Components Within a Container for more details about using layout managers

    Login or Signup to reply.
  4. I’d like to use the combination of BorderLayout and BoxLayout. BorderLayout let me put the component based on their relative location’s relation and BoxLayout let me manage the subtle distance ( create some white space). You can use component.setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right)); to achieve this goal too.

    Here is a demo and hope it can help you.

    import java.awt.BorderLayout;
    import java.awt.Color;
    
    import javax.swing.BorderFactory;
    import javax.swing.Box;
    import javax.swing.BoxLayout;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JList;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextField;
    import javax.swing.event.ListSelectionEvent;
    import javax.swing.event.ListSelectionListener;
    
    public class LayoutTest{
    
        private JTextField jTextField;
    
        public void createUI(){
            JFrame frame = new JFrame("Layout Test");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setResizable(true);
    
            JPanel mainPanel = new JPanel();
            mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
    
    
            mainPanel.add(new TextFieldPanel());
    
            mainPanel.add(Box.createVerticalStrut(8));
    
            mainPanel.add(new ListPanel());
    
            mainPanel.add(Box.createVerticalStrut(8));
    
            mainPanel.add(new ButtonPanel());
    
            frame.add(mainPanel,BorderLayout.CENTER);
    
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
    
        }
    
        public static void main(String[] args) {
            LayoutTest layoutTest = new LayoutTest();
            layoutTest.createUI();
        }
    
    
        @SuppressWarnings("serial")
        class TextFieldPanel extends JPanel{
            public TextFieldPanel(){
                setLayout(new BorderLayout());
                jTextField = new JTextField();
                jTextField.setEditable(false);
                add(jTextField,BorderLayout.CENTER);
            }
        }
    
        @SuppressWarnings("serial")
        class ListPanel extends JPanel implements ListSelectionListener{
            private JList<String> list;
    
            public ListPanel(){
                setLayout(new BorderLayout());
                String stringArr[] = new String[30];
                for (int i = 0; i < 30; i++) {
                    stringArr[i] = "JList :This line is item" + i;
                }
                list = new JList<String>(stringArr);
                JScrollPane scrollPane = new JScrollPane(list);
                add(scrollPane,BorderLayout.CENTER);
                setBackground(new Color(211,211,211));
    
                list.addListSelectionListener(this);
            }
    
            @Override
            public void valueChanged(ListSelectionEvent e) {
                // TODO Auto-generated method stub
                jTextField.setText(list.getSelectedValue());
            }
        }
    
        @SuppressWarnings("serial")
        class ButtonPanel extends JPanel{
            public ButtonPanel(){       
                JButton button1 = new JButton("Button1");
                JButton button2 = new JButton("Button2");
                JButton button3 = new JButton("Button3");
    
                setLayout(new BorderLayout());
                add(button1,BorderLayout.WEST);
                add(button2,BorderLayout.CENTER);
                add(button3,BorderLayout.EAST);
            }
        }
    }
    

    Here is the effect:

    enter image description here

    enter image description here

    You can use BoxLayout for ButtonPanel if you don’t want to let the button’s size change.

    @SuppressWarnings("serial")
    class ButtonPanel extends JPanel{
        public ButtonPanel(){       
            JButton button1 = new JButton("Button1");
            JButton button2 = new JButton("Button2");
            JButton button3 = new JButton("Button3");
    
            setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
    
            add(button1);
            add(Box.createHorizontalStrut(8));
            add(button2);
            add(Box.createHorizontalStrut(8));
            add(button3);
        }
    }
    

    And the effect is like this:

    enter image description here

    For more infomation about using BoxLayout to generate whitespace, you can refer to https://stackoverflow.com/a/22525005/3378204

    Login or Signup to reply.
  5. HVLayout keeps the relative size of the components with respect to the size of the window, that is, if you configure components to have a relative size (e.g. buttons usually do not grow or shrink – they stick to their preferred size). This SO question was one of the motivations for me to push HVLayout to a release and a screenshot is included (showing big window size, smalll size and preferred “default” size):

    rel-to-window

    Source code for the window is in RelativeToWindowSize.java

    A number of helper-classes from HVLayout are used to build the window, so I don’t think it will be of much use here, but to get an impression, the “build window” part shown below:

    public RelativeToWindowSize build() {
    
        CSize cs = new CSize();
        CForm form = new CForm(new VBox(new Insets(2, 4, 2, 4)), cs);
        addTitledBorder(form.get(), "Vertical box", Color.BLACK);
        form.add(new JScrollPane(
                    tfield = new JTextArea("Value that changes with value choosen from list.nhttp://stackoverflow.com/questions/24462297/layout-relative-to-screensize/")
                )).csize().setAreaSize(1.0f, 2.5f).fixedMinHeight().setMaxHeight(4.0f);
        // tfield shows mono-spaced font by default.
        tfield.setFont(SwingUtils.getUIFont());
        form.add(new JScrollPane(vlist = new JList<String>(getListValues())))
                .csize().setAreaSize(1.0f, 5.0f);
    
        form.addChild(new HBox());
        addTitledBorder(form.get(), "Horizontal box", Color.RED);
        form.addChild(new HBox(SwingConstants.CENTER));
        addTitledBorder(form.get(), "Centered box.", Color.BLUE);
        form.add(createButton(cs, "Add"));
        form.add(createButton(cs, "Modify"));
        form.up();
        form.addChild(new HBox(SwingConstants.TRAILING));
        addTitledBorder(form.get(), "Trailing box", Color.GREEN);
        form.add(createButton(cs, "Delete"));
    
        setContentPane(form.getRoot());
        pack();
        setLocationByPlatform(true);
        //applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
        vlist.addListSelectionListener(this);
        log.debug(getClass().getName() + " build.");
        return this;
    }
    
    private Component createButton(CSize cs, String text) {
        // For purpose of demo, let button shrink in width.
        return cs.set(new TButton(text)).setFixed().shrinkWidth(0.33f).get();
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search