Layout - Relative to screensize

半腔热情 提交于 2021-01-29 04:41:19

问题


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?


回答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




回答2:


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




回答3:


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




回答4:


Try GridBagLayout.

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




回答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();
}


来源:https://stackoverflow.com/questions/24462297/layout-relative-to-screensize

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!