所以我是一名计算机科学专业的学生,我已经读了第一年。我想创建一个简单的程序,我意识到我已经厌倦了不使用布局;
this.setLayout(null);
为每个组件添加边界是非常烦人的。好吧,我一直在使用JPanel
组件和GridLayout
,这使我的工作更容易一些。但我厌倦了。
我非常关心我制作的GUI的外观,并且在我开始添加代码功能之前,使用几乎一半的时间编程使GUI看起来很好。通过不使用布局和添加边界,我被迫setResizable(false)
,因为如果我改变JFrame的大小,它看起来很糟糕。
我一直在搜索,我知道BorderLayout
和FlowLayout
,但我不喜欢它们。是否有任何布局可以保持组件相对于窗口大小的相对大小?
例如,我想创建一个如下所示的简单程序:( Photoshop中的快速草图)
我可以轻松地使用3个面板制作它,但正如我所说,如果我改变框架的大小,一切都会保持原位而不是相对于窗口大小。
你们能帮助我吗?
答案 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
上的按钮
使用
实现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);
}
}
}
效果如下:
如果您不想让按钮的大小发生变化,可以将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);
}
}
效果是这样的:
有关使用BoxLayout生成空格的更多信息,可以参考https://stackoverflow.com/a/22525005/3378204
答案 3 :(得分:1)
您的草图实际上非常接近official tutorial中的一个示例。
答案 4 :(得分:0)
HVLayout保持组件相对于窗口大小的相对大小,也就是说,如果将组件配置为具有相对大小(例如,按钮通常不会增大或缩小 - 它们会坚持使用首选尺寸)。这个SO问题是我将HVLayout推向发布的动机之一,并且包含了截图(显示大窗口大小,小尺寸和首选&#34;默认&#34;大小):
窗口的源代码在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();
}