在Swing GUI中提供空白区域

一个没有空白的GUI显得“拥挤”。 我怎样才能提供空白,而不是明确地设置组件的位置或大小?

使用各种LayoutManagers可以提供各种组件之间的间隔。

1.)BorderLayout:

  • 重载的构造函数: BorderLayout(int horizo​​ntalGap,int verticalGap)
  • Getter和setter方法

    对于水平间距 BorderLayout.getHgap()和BorderLayout.setHgap(int hgap)

    对于垂直间距 BorderLayout.getVgap()和BorderLayout.setVgap()

2.)FlowLayout:

  • 重载的构造函数: FlowLayout(int align,int hgap,int vgap)
  • Getter和setter方法

    对于水平间距 FlowLayout.getHgap()和FlowLayout.setHgap(int hgap)

    对于垂直间距 FlowLayout.getVgap()和FlowLayout.setVgap()

3.)GridLayout:

  • 重载的构造函数: GridLayout(int行,int列,int hgap,int vgap)
  • Getter和setter方法

    对于水平间距 GridLayout.getHgap()和GridLayout.setHgap(int hgap)

    对于垂直间距 GridLayout.getVgap()和GridLayout.setVgap()

4.)GridBagLayout:

GridBagConstraints.insets

5.)CardLayout( 示例 ):

CardLayout(int hGap,int vGap)

显示所有构造函数的例子

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class LayoutExample { private final int hGap = 5; private final int vGap = 5; private String[] borderConstraints = { BorderLayout.PAGE_START, BorderLayout.LINE_START, BorderLayout.CENTER, BorderLayout.LINE_END, BorderLayout.PAGE_END }; private JButton[] buttons; private GridBagConstraints gbc; private JPanel borderPanel; private JPanel flowPanel; private JPanel gridPanel; private JPanel gridBagPanel; private JPanel cardPanel; public LayoutExample() { buttons = new JButton[16]; gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.FIRST_LINE_START; gbc.insets = new Insets(hGap, vGap, hGap, vGap); } private void displayGUI() { JFrame frame = new JFrame("Layout Example"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); JPanel contentPane = new JPanel( new GridLayout(0, 1, hGap, vGap)); contentPane.setBorder( BorderFactory.createEmptyBorder(hGap, vGap, hGap, vGap)); borderPanel = new JPanel(new BorderLayout(hGap, vGap)); borderPanel.setBorder( BorderFactory.createTitledBorder("BorderLayout")); borderPanel.setOpaque(true); borderPanel.setBackground(Color.WHITE); for (int i = 0; i < 5; i++) { buttons[i] = new JButton(borderConstraints[i]); borderPanel.add(buttons[i], borderConstraints[i]); } contentPane.add(borderPanel); flowPanel = new JPanel(new FlowLayout( FlowLayout.CENTER, hGap, vGap)); flowPanel.setBorder( BorderFactory.createTitledBorder("FlowLayout")); flowPanel.setOpaque(true); flowPanel.setBackground(Color.WHITE); for (int i = 5; i < 8; i++) { buttons[i] = new JButton(Integer.toString(i)); flowPanel.add(buttons[i]); } contentPane.add(flowPanel); gridPanel = new JPanel(new GridLayout(2, 2, hGap, vGap)); gridPanel.setBorder( BorderFactory.createTitledBorder("GridLayout")); gridPanel.setOpaque(true); gridPanel.setBackground(Color.WHITE); for (int i = 8; i < 12; i++) { buttons[i] = new JButton(Integer.toString(i)); gridPanel.add(buttons[i]); } contentPane.add(gridPanel); gridBagPanel = new JPanel(new GridBagLayout()); gridBagPanel.setBorder( BorderFactory.createTitledBorder("GridBagLayout")); gridBagPanel.setOpaque(true); gridBagPanel.setBackground(Color.WHITE); buttons[12] = new JButton(Integer.toString(12)); addComp(gridBagPanel, buttons[12], 0, 0, 1, 1 , GridBagConstraints.BOTH, 0.33, 0.5); buttons[13] = new JButton(Integer.toString(13)); addComp(gridBagPanel, buttons[13], 1, 0, 1, 1 , GridBagConstraints.BOTH, 0.33, 0.5); buttons[14] = new JButton(Integer.toString(14)); addComp(gridBagPanel, buttons[14], 0, 1, 2, 1 , GridBagConstraints.BOTH, 0.66, 0.5); buttons[15] = new JButton(Integer.toString(15)); addComp(gridBagPanel, buttons[15], 2, 0, 1, 2 , GridBagConstraints.BOTH, 0.33, 1.0); contentPane.add(gridBagPanel); cardPanel = new JPanel(new CardLayout(hGap, vGap)); cardPanel.setBorder( BorderFactory.createTitledBorder("CardLayout")); cardPanel.setOpaque(true); cardPanel.setBackground(Color.WHITE); cardPanel.add(getPanel(Color.BLUE)); cardPanel.add(getPanel(Color.GREEN)); contentPane.add(cardPanel); frame.setContentPane(contentPane); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } private JPanel getPanel(Color bColor) { JPanel panel = new JPanel(new FlowLayout( FlowLayout.CENTER, hGap, vGap)); panel.setOpaque(true); panel.setBackground(bColor.darker().darker()); JButton swapperButton = new JButton("Next"); swapperButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { CardLayout cardLayout = (CardLayout) cardPanel.getLayout(); cardLayout.next(cardPanel); } }); panel.add(swapperButton); return panel; } private void addComp(JPanel panel, JComponent comp , int x, int y, int gWidth , int gHeight, int fill , double weightx, double weighty) { gbc.gridx = x; gbc.gridy = y; gbc.gridwidth = gWidth; gbc.gridheight = gHeight; gbc.fill = fill; gbc.weightx = weightx; gbc.weighty = weighty; panel.add(comp, gbc); } public static void main(String[] args) { Runnable runnable = new Runnable(){ @Override public void run() { new LayoutExample().displayGUI(); } }; EventQueue.invokeLater(runnable); } } 

输出:

LAYOUTIMAGE

Swing GUI中提供了多种方法来提供组件之间的分离和组件周围的空白区域:

  • JToolBar有方法addSeparator()addSeparator(Dimension)
  • JMenu使用更适合菜单的间隔组件,可通过addSeparator()

但更一般地说,请看:

  • 间距可以在布局构造函数中定义。
  • 国界。

下面是使用布局分隔符hGapvGap值&边框(特别是EmptyBorder )来提供“白色”(实际上显示为“红色”以使其非常明显)空间的示例。 调整旋转器以查看结果。

没有GUI空白

用GUI空白

 import java.awt.*; import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.event.*; public class WhiteSpace { private JPanel gui = null; private BorderLayout mainLayout; private FlowLayout buttonLayout; private EmptyBorder border; public Container getGui() { if (gui==null) { mainLayout = new BorderLayout(0,0); gui = new JPanel(mainLayout); gui.setBackground(Color.RED); border = new EmptyBorder(0,0,0,0); JTree tree = new JTree(); tree.setVisibleRowCount(10); for (int ii = tree.getRowCount(); ii>-1; ii--) { tree.expandRow(ii); } gui.add(new JScrollPane( tree, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.LINE_START); gui.add(new JScrollPane(new JTextArea(10,30))); buttonLayout = new FlowLayout(FlowLayout.CENTER,0,0); JPanel buttonPanel = new JPanel(buttonLayout); gui.add(buttonPanel, BorderLayout.PAGE_START); buttonPanel.add(new JLabel("H Gap")); final JSpinner hSpinner = new JSpinner(new SpinnerNumberModel(0,0,15,1)); buttonPanel.add(hSpinner); buttonPanel.add(new JLabel("V Gap")); final JSpinner vSpinner = new JSpinner(new SpinnerNumberModel(0,0,15,1)); buttonPanel.add(vSpinner); buttonPanel.add(new JLabel("H Border")); final JSpinner hBorderSpinner = new JSpinner(new SpinnerNumberModel(0,0,15,1)); buttonPanel.add(hBorderSpinner); buttonPanel.add(new JLabel("V Border")); final JSpinner vBorderSpinner = new JSpinner(new SpinnerNumberModel(0,0,15,1)); buttonPanel.add(vBorderSpinner); ChangeListener changeListener = new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { int hGap = ((Integer)hSpinner.getValue()).intValue(); int vGap = ((Integer)vSpinner.getValue()).intValue(); int hBorder = ((Integer)hBorderSpinner.getValue()).intValue(); int vBorder = ((Integer)vBorderSpinner.getValue()).intValue(); adjustWhiteSpace(hGap,vGap,hBorder,vBorder); } }; hSpinner.addChangeListener(changeListener); vSpinner.addChangeListener(changeListener); hBorderSpinner.addChangeListener(changeListener); vBorderSpinner.addChangeListener(changeListener); } return gui; } private void adjustWhiteSpace(int hGap, int vGap, int hBorder, int vBorder) { mainLayout.setHgap(hGap); mainLayout.setVgap(vGap); buttonLayout.setHgap(hGap); gui.setBorder(new EmptyBorder(vBorder,hBorder,vBorder,hBorder)); Container c = gui.getTopLevelAncestor(); if (c instanceof Window) { Window w = (Window)c; w.pack(); } } public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { WhiteSpace ws = new WhiteSpace(); // the GUI as seen by the user (without frame) Container gui = ws.getGui(); JFrame f = new JFrame("White (OK Red) Space"); f.add(gui); // Ensures JVM closes after frame(s) closed and // all non-daemon threads are finished f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // See http://stackoverflow.com/a/7143398/418556 for demo. f.setLocationByPlatform(true); // ensures the frame is the minimum size it needs to be // in order display the components within it f.setResizable(false); f.pack(); // should be done last, to avoid flickering, moving, // resizing artifacts. f.setVisible(true); } }; SwingUtilities.invokeLater(r); } } 

当您使用BoxLayoutBox.createVerticalGlue()方法可以帮助您制作一些空白区域。

另一种方法是BorderFactory.createEmptyBorder(int top, int left, int bottom, int right) 。 它可以帮助您在组件周围创build一些空白区域。

感谢Andrew Thompson的提醒。我在最近几天修改了BoxLayout,发现Box.createVerticalGlue()可以根据面板的大小添加一些空白区域,并且不能设置空白长度的显式像素值。 Box.createVerticalStrut()可以做到这一点。 这是一个MCTaRE,并显示这两种方法的效果。

在这里输入图像描述

 import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; public class WhiteSpace extends JFrame{ static WhiteSpace whiteSpace; DemoPanel demoPanel; boolean withGlue; JSpinner spinner; public WhiteSpace(){ initialWindow(); demoPanel = new DemoPanel(); ActionPanel actionPanel = new ActionPanel(); setLayout(new BorderLayout()); getContentPane().add(actionPanel,BorderLayout.NORTH); getContentPane().add(demoPanel,BorderLayout.CENTER); setVisible(true); } public void initialWindow(){ setSize(220, 300); setTitle("White Space"); setResizable(false); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); //Show the window in the middle of the screen } /** * @param args */ public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { whiteSpace = new WhiteSpace(); } }; SwingUtilities.invokeLater(runnable); } class DemoPanel extends JPanel{ //Show the vertical white space between label1 and label2 JLabel label1; JLabel label2; public void initialDemoPanel(){ setBorder(BorderFactory.createTitledBorder(getBorder(), "DemoPanel", TitledBorder.LEADING, TitledBorder.TOP, new Font("Default",Font.PLAIN,10), Color.gray)); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); label1 = new JLabel("This is first line"); label2 = new JLabel("This is second line"); } public DemoPanel(){ initialDemoPanel(); add(label1); if(withGlue){ add(Box.createVerticalGlue()); } add(label2); } public DemoPanel(int strutValue){ initialDemoPanel(); add(label1); add(Box.createVerticalStrut(strutValue)); add(label2); } } class ActionPanel extends JPanel{ public ActionPanel(){ setBorder(BorderFactory.createTitledBorder(getBorder(), "ActionPanel", TitledBorder.LEADING, TitledBorder.TOP, new Font("Default",Font.PLAIN,10), Color.gray)); setLayout(new BoxLayout(this,BoxLayout.X_AXIS)); JRadioButton glueButton = new JRadioButton("With Glue"); glueButton.addActionListener(new glueButtonListener()); add(glueButton); add(Box.createHorizontalStrut(10)); //To create horizontal white space JLabel strutLabel = new JLabel("Strut Value"); add(strutLabel); spinner = new JSpinner(new SpinnerNumberModel(0,0,50,1)); spinner.addChangeListener(new spinnerListener()); add(spinner); //public SpinnerNumberModel(Number value,Comparable minimum,Comparable maximum,Number stepSize) } } class glueButtonListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { spinner.setValue(new Integer(0)); withGlue = (withGlue == true ? false:true); whiteSpace.getContentPane().remove(demoPanel); demoPanel = new DemoPanel(); whiteSpace.getContentPane().add(demoPanel,BorderLayout.CENTER); whiteSpace.getContentPane().validate(); } } class spinnerListener implements ChangeListener{ @Override public void stateChanged(ChangeEvent e) { int strutValue = (Integer) spinner.getValue(); whiteSpace.getContentPane().remove(demoPanel); demoPanel = new DemoPanel(strutValue); whiteSpace.getContentPane().add(demoPanel,BorderLayout.CENTER); whiteSpace.getContentPane().validate(); } } } 

Box.createHorizontalGlue()Box.createHorizontalStrut(int height)也可以使用。 此外, Box.createRigidArea(Dimension d)也具有创build空白的能力。

MigLayout有多种创build空间的方式。 (在这个布局中空间被称为间隙)间隙可以在布局约束的最高层创build,可以在行和列之间创build间隙,也可以在具有组件约束的单个组件之间设置间隙。 在一个名为insets的容器的边界周围还有一些特定的空白,它们有自己特定的关键字。

以下示例创build了所有这些差距:

 package com.zetcode; import java.awt.EventQueue; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import net.miginfocom.swing.MigLayout; public class MigLayoutGaps2 extends JFrame { public MigLayoutGaps2() { initUI(); setTitle("Gaps"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } private void initUI() { JPanel base = new JPanel(new MigLayout("flowy, ins 30, gap 15")); setContentPane(base); JPanel pnl1 = new JPanel(); pnl1.setBorder( BorderFactory.createTitledBorder("Grid gaps") ); pnl1.setLayout(new MigLayout("gap 5 5, ins 10, wrap 3")); pnl1.add(new JButton("1")); pnl1.add(new JButton("2")); pnl1.add(new JButton("3")); pnl1.add(new JButton("4")); pnl1.add(new JButton("5")); pnl1.add(new JButton("6")); JPanel pnl2 = new JPanel(); pnl2.setBorder( BorderFactory.createTitledBorder("Column gaps") ); pnl2.setLayout(new MigLayout("wrap 3", "[]10[]")); JLabel lbl1 = new JLabel(); lbl1.setBorder( BorderFactory.createEtchedBorder() ); JLabel lbl2 = new JLabel(); lbl2.setBorder( BorderFactory.createEtchedBorder() ); JLabel lbl3 = new JLabel(); lbl3.setBorder( BorderFactory.createEtchedBorder() ); pnl2.add(lbl1, "w 40, h 110"); pnl2.add(lbl2, "w 40, h 110"); pnl2.add(lbl3, "w 40, h 110"); JPanel pnl3 = new JPanel(); pnl3.setBorder( BorderFactory.createTitledBorder("Row gaps") ); pnl3.setLayout(new MigLayout("wrap", "", "[]15[]")); JLabel lbl4 = new JLabel(); lbl4.setBorder( BorderFactory.createEtchedBorder() ); JLabel lbl5 = new JLabel(); lbl5.setBorder( BorderFactory.createEtchedBorder() ); JLabel lbl6 = new JLabel(); lbl6.setBorder( BorderFactory.createEtchedBorder() ); pnl3.add(lbl4, "w 150, h 20"); pnl3.add(lbl5, "w 150, h 20"); pnl3.add(lbl6, "w 150, h 20"); JPanel pnl4 = new JPanel(); pnl4.setBorder( BorderFactory.createTitledBorder("Component gaps") ); pnl4.setLayout(new MigLayout()); pnl4.add(new JLabel("Name:"), "gapright 5"); pnl4.add(new JTextField(10), "gapbottom 20, gaptop 20"); base.add(pnl1); base.add(pnl2); base.add(pnl3); base.add(pnl4); pack(); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { MigLayoutGaps2 ex = new MigLayoutGaps2(); ex.setVisible(true); } }); } } 

我们在布局中有四个面板。 每个面板都有一个MigLayoutpipe理器。

 JPanel base = new JPanel(new MigLayout("flowy, ins 30, gap 15")); 

此行创build容器插页和面板之间的垂直间隙。

 pnl1.setLayout(new MigLayout("gap 5 5, ins 10, wrap 3")); 

在这里,我们为整个网格结构应用间隙,并设置容器间隙。

 pnl2.setLayout(new MigLayout("wrap 3", "[]10[]")); 

这条线创build列之间的差距。

 pnl3.setLayout(new MigLayout("wrap", "", "[]15[]")); 

行间隙用这个代码定义。

 pnl4.add(new JLabel("Name:"), "gapright 5"); pnl4.add(new JTextField(10), "gapbottom 20, gaptop 20"); 

最后,有可能在各个组件之间产生差距。

差距

JGoodies FormLayout

作者Karsten Lentzsch收集了关于UIdevise的演示 。 特别是这个PDF说明了审美空白的需要。 添加有意义的空间,同时也注意杂乱从麦糠中分离出小麦。