Графический интерфейс без пробела выглядит "переполненным". Как я могу обеспечить пустое пространство, не прибегая к явно устанавливая положение или размер компонентов?
Обеспечение пробела в графическом интерфейсе Swing
Ответ 1
В графическом интерфейсе Swing имеется несколько способов обеспечить разделение между компонентами и пробелы вокруг компонентов:
-
JToolBar
имеет методыaddSeparator()
иaddSeparator(Dimension)
. -
JMenu
использует компонент интервала, более подходящий для меню, доступный черезaddSeparator()
.
Но в общем, посмотрите:
- Интервал, который может быть определен в конструкторах макета.
- Границы.
Вот пример использования разделителей макетов hGap
и vGap
значений и границ (в частности, EmptyBorder
), чтобы обеспечить "белый" (фактически показано как красный, чтобы сделать его очень очевидное) пространство. Отрегулируйте прядильщики, чтобы увидеть результат.
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);
}
}
Ответ 2
Используя различные LayoutManagers
, можно обеспечить промежуток между различными компонентами.
1.) BorderLayout:
- Перегруженный конструктор: BorderLayout (int horizontalGap, int verticalGap)
-
Методы получения и настройки
Для горизонтального интервала : BorderLayout.getHgap() и BorderLayout.setHgap(int hgap )
Для вертикального интервала : BorderLayout.getVgap() и BorderLayout.setVgap()
2.) FlowLayout:
- Перегруженный конструктор: FlowLayout (int align, int hgap, int vgap)
-
Методы получения и настройки
Для горизонтального интервала : FlowLayout.getHgap() и FlowLayout.setHgap(int hgap )
Для вертикального интервала : FlowLayout.getVgap() и FlowLayout.setVgap()
3.) GridLayout:
- Перегруженный конструктор: GridLayout (int rows, int columns, int hgap, int vgap)
-
Методы получения и настройки
Для горизонтального интервала : GridLayout.getHgap() и GridLayout.setHgap(int hgap )
Для вертикального интервала : GridLayout.getVgap() и GridLayout.setVgap()
4.) GridBagLayout:
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);
}
}
ВЫХОД:
Ответ 3
Когда вы используете метод BoxLayout
, Box.createVerticalGlue()
может помочь вам сделать несколько пробелов.
Другой метод - BorderFactory.createEmptyBorder(int top, int left, int bottom, int right)
. Это может помочь вам сделать небольшое пространство вокруг компонента.
Спасибо, 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)
обладает способностью также создавать пустое пространство.
Ответ 4
MigLayout
имеет несколько способов создания пространства. (Пространство называется разрывом в этом макете.)
Пробелы могут быть созданы на самом высоком уровне с ограничениями макета, возможно
создавать промежутки между строками и столбцом, а промежутки могут также устанавливаться между отдельными
компоненты с ограничениями компонентов. Существуют также определенные пробелы вокруг границ
контейнера, называемого вставками, для которых задано собственное определенное ключевое слово.
Следующий пример создает все эти пробелы:
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);
}
});
}
}
У нас есть четыре панели в макете. Каждая из этих панелей имеет диспетчер MigLayout
.
JPanel base = new JPanel(new MigLayout("flowy, ins 30, gap 15"));
Эта строка создает вставки контейнера и вертикальные промежутки между панелями.
pnl1.setLayout(new MigLayout("gap 5 5, ins 10, wrap 3"));
Здесь мы применяем пробелы для всей структуры сетки и также устанавливаем пробелы в контейнерах.
pnl2.setLayout(new MigLayout("wrap 3", "[]10[]"));
Эта строка создает промежутки между столбцами.
pnl3.setLayout(new MigLayout("wrap", "", "[]15[]"));
Разделительные интервалы определяются с помощью этого кода.
pnl4.add(new JLabel("Name:"), "gapright 5");
pnl4.add(new JTextField(10), "gapbottom 20, gaptop 20");
Наконец, можно создать промежутки между отдельными компонентами.
Ответ 5
Автор Karsten Lentzsch имеет коллекцию presentations в дизайне пользовательского интерфейса. В частности, этот PDF говорит о необходимости эстетических пробелов. Добавляя осмысленное пространство, а также обращая внимание на беспорядок, отделяет пшеницу от мякины.
Ответ 6
Всякий раз, когда у меня возникает эта проблема, я просто использую JPanels. Например, в GridLayout:
JFrame frame = new JFrame;
frame.setLayout(new GridLayout(2, 0));
//We want the bottom left to be blank
frame.add(new JLabel("Top Left"));
frame.add(new JLabel("Top Right"));
//This is the position we want empty
frame.add(new JPanel());
//Now we can continue with the rest of the script
Надеюсь, это помогло :)