布局 - 相对于屏幕尺寸

时间:2014-06-27 23:58:44

标签: java swing layout layout-manager

所以我是一名计算机科学专业的学生,​​我已经读了第一年。我想创建一个简单的程序,我意识到我已经厌倦了不使用布局;

this.setLayout(null);

为每个组件添加边界是非常烦人的。好吧,我一直在使用JPanel组件和GridLayout,这使我的工作更容易一些。但我厌倦了。

我非常关心我制作的GUI的外观,并且在我开始添加代码功能之前,使用几乎一半的时间编程使GUI看起来很好。通过不使用布局和添加边界,我被迫setResizable(false),因为如果我改变JFrame的大小,它看起来很糟糕。

我一直在搜索,我知道BorderLayoutFlowLayout,但我不喜欢它们。是否有任何布局可以保持组件相对于窗口大小的相对大小?

例如,我想创建一个如下所示的简单程序:( Photoshop中的快速草图)

enter image description here

我可以轻松地使用3个面板制作它,但正如我所说,如果我改变框架的大小,一切都会保持原位而不是相对于窗口大小。

你们能帮助我吗?

5 个答案:

答案 0 :(得分:3)

这个设计让我看起来适合BorderLayout,在北方,你有values that changes你有主要部分的中心,南边有你的按钮。

Link to the Oracle Border Layout

您可以将此BorderLayout应用于JFrame,然后为NORTH,CENTER和SOUTH部分创建3个JPanel。如果您想对组件和面板使用响应式设计,请查看GridBagLayout,它比GridLayout更灵活

答案 1 :(得分:2)

布局管理是一个非常复杂的问题,我认为人们并不真正理解它究竟是多么复杂。

没有任何一种布局可以实现您想要的一切,在大多数情况下,您需要采用两种或更多布局,尤其是当您的要求变得更加复杂时。

例如,以下只是基座上的BorderLayout和使用JPanel

FlowLayout上的按钮

Layout Layout

使用

实现
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);

对于更复杂的布局,我会考虑使用GridBagLayout之类的东西。您可能还想将MigLayout视为替代

有关使用布局管理器的更多详细信息,请查看Laying Out Components Within a Container

答案 2 :(得分:2)

我想使用BorderLayout和BoxLayout的组合。 BorderLayout让我根据相对位置的关系放置组件,BoxLayout让我管理微妙的距离(创建一些空白区域)。您可以使用component.setBorder(BorderFactory.createEmptyBorder(top,left,bottom,right));也实现了这个目标。

这是一个演示,希望它可以帮助你。

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);
        }
    }
}

效果如下:

enter image description here

enter image description here

如果您不想让按钮的大小发生变化,可以将BoxLay用于ButtonPanel。

@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);
    }
}

效果是这样的:

enter image description here

有关使用BoxLayout生成空格的更多信息,可以参考https://stackoverflow.com/a/22525005/3378204

答案 3 :(得分:1)

尝试GridBagLayout

您的草图实际上非常接近official tutorial中的一个示例。

答案 4 :(得分:0)

HVLayout保持组件相对于窗口大小的相对大小,也就是说,如果将组件配置为具有相对大小(例如,按钮通常不会增大或缩小 - 它们会坚持使用首选尺寸)。这个SO问题是我将HVLayout推向发布的动机之一,并且包含了截图(显示大窗口大小,小尺寸和首选&#34;默认&#34;大小):
rel-to-window
窗口的源代码在RelativeToWindowSize.java
使用HVLayout中的一些辅助类来构建窗口,所以我不认为它会在这里有多大用处,但是为了给人留下印象,&#34;构建窗口&#34 ;部分如下所示:

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