Забезпечення білого простору в інтерфейсі Swing


161

Графічний інтерфейс без пробілу видається "переповненим". Як я можу забезпечити пробіл, не вдаючись до явного встановлення положення чи розміру компонентів?



1
використовувати LayoutManager, який підтримує прогалини в семантичному виразі. Ви бачите, що він наближається, чи не так :-) MigLayout на допомогу: ви визначаєте сітку та пропуски між подібними спорідненими, непов'язаними абзацами - aftet, які просто додають компоненти
kleopatra

Відповіді:


111

Використовуючи різні, LayoutManagersможна забезпечити відстань між різними компонентами.

1.) Розташування кордону:

2.) Макет потоку:

3.) Розкладка Grid:

4.) Макет GridBagLayout:

GridBagConstraints.insets

5.) Макет карт ( приклад ):

Картковий макет (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);
    }
}

ВИХІД:

РОЗМІСТЕННЯ


6
+1 Я luuuuuv мені деякі вставки GridBagConstraints. Ми використовуємо GBL дуже багато, тому я написав кілька допоміжних класів, які роблять брудну роботу для мене, щоб код GBL був досить стислим і читабельним. Як і в цьому прикладі, я використовую Insets за замовчуванням, так що мені не доведеться вводити його щоразу, і отриманий вигляд - це більш "розслаблений" макет.
splungebob

63

У графічному інтерфейсі Swing є кілька способів забезпечити розділення між компонентами та пробілом навколо компонентів:

Але більш загально, зверніть увагу на:

  • Простір, як можна визначити в конструкторах макетів.
  • Межі.

Ось приклад використання роздільника макета hGapта vGapзначень та меж (зокрема, 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 = 
        new BorderLayout(0, 0);
    private final FlowLayout buttonLayout = 
            new FlowLayout(FlowLayout.CENTER, 0, 0);
    private final JPanel buttonPanel = new JPanel(buttonLayout);
    private final SpinnerNumberModel hModel = 
            new SpinnerNumberModel(0, 0, 15, 1);
    private final SpinnerNumberModel vModel = 
            new SpinnerNumberModel(0, 0, 15, 1);
    private final SpinnerNumberModel hBorderModel = 
            new SpinnerNumberModel(0, 0, 15, 1);
    private final SpinnerNumberModel vBorderModel = 
            new SpinnerNumberModel(0, 0, 15, 1);
    private ChangeListener changeListener;

    public Container getGui() {
        if (gui == null) {
            gui = new JPanel(mainLayout);
            gui.setBackground(Color.RED);

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

            gui.add(buttonPanel, BorderLayout.PAGE_START);

            changeListener = (ChangeEvent e) -> {
                int hGap = hModel.getNumber().intValue();
                int vGap = vModel.getNumber().intValue();
                int hBorder = hBorderModel.getNumber().intValue();
                int vBorder = vBorderModel.getNumber().intValue();
                adjustWhiteSpace(hGap, vGap, hBorder, vBorder);
            };

            addModel("H Gap", hModel);
            addModel("V Gap", vModel);
            addModel("H Border", hBorderModel);
            addModel("V Border", vBorderModel);
        }

        return gui;
    }

    private void addModel(String label, SpinnerNumberModel model) {
        buttonPanel.add(new JLabel(label));
        final JSpinner spinner = new JSpinner(model);
        spinner.addChangeListener(changeListener);
        buttonPanel.add(spinner);
    }

    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 = () -> {
            WhiteSpace ws = new WhiteSpace();
            Container gui1 = ws.getGui();
            JFrame f = new JFrame("White (OK Red) Space");
            f.add(gui1);
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setLocationByPlatform(true);
            f.setResizable(false);
            f.pack();
            f.setVisible(true);
        };
        SwingUtilities.invokeLater(r);
    }
}

20

Коли ви користуєтесь BoxLayout,Box.createVerticalGlue() метод може допомогти вам зробити деякі прогалини.

Інший метод BorderFactory.createEmptyBorder(int top, int left, int bottom, int right) . Це може допомогти вам зробити пробіл навколо компонента.

Дякую за нагадування Ендрю Томпсона. Я переглянув 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)має можливість також створювати білий простір.


12

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

Нарешті, можливо створити прогалини між окремими компонентами.

Прогалини


7

JGoodies FormLayout .

Автор Карстен Ленцш має колекцію презентацій про дизайн інтерфейсу. Зокрема, цей PDF говорить про необхідність естетичного простору. Додаючи значущого простору, при цьому звертаючи увагу на захаращення, відокремлюється пшениця від пшениці.


0

Щоразу, коли у мене є ця проблема, я просто використовую JPanel. Наприклад, у 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

Сподіваюся, це допомогло :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.