0

图形用户界面

所以基本上我想创建这种类型的 GUI,但由于我对 Java GUI 的经验不足,我无法弄清楚要使用哪个布局管理器。我尝试过 Flow、Border、Grid,但它们都不允许我创建这种 GUI 而不会弄乱某处的对齐方式。

有什么建议么?我应该如何决定未来的布局管理器,还是它会随着经验而来?

我更喜欢使用简单易用的布局,因为这是一个非常基本的 GUI,我认为不需要像 MiGLayout 这样的东西。

4

4 回答 4

4

我会使用复合面板和布局的组合。除了使布局更容易工作之外,您还可以在他们自己的类中隔离责任区域。

在此处输入图像描述

public class TestLayout13 {

    public static void main(String[] args) {
        new TestLayout13();
    }

    public TestLayout13() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new FormPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class FormPane extends JPanel {

        public FormPane() {
            setBorder(new EmptyBorder(8, 8, 8, 8));
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weightx = 1;

            NamePane namePane = new NamePane();
            namePane.setBorder(new CompoundBorder(new TitledBorder("Name"), new EmptyBorder(4, 4, 4, 4)));
            add(namePane, gbc);

            gbc.gridy++;

            EMailPane emailPane = new EMailPane();
            emailPane.setBorder(new CompoundBorder(new TitledBorder("E-Mail"), new EmptyBorder(4, 4, 4, 4)));
            add(emailPane, gbc);
        }

    }

    public class NamePane extends JPanel {

        public NamePane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.EAST;

            add(new JLabel("First Name:"), gbc);
            gbc.gridx += 2;
            add(new JLabel("Last Name:"), gbc);
            gbc.gridy++;
            gbc.gridx = 0;
            add(new JLabel("Title:"), gbc);
            gbc.gridx += 2;
            add(new JLabel("Nickname:"), gbc);

            gbc.gridx = 1;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.anchor = GridBagConstraints.WEST;
            gbc.weightx = 0.5;
            add(new JTextField(10), gbc);
            gbc.gridx += 2;
            add(new JTextField(10), gbc);
            gbc.gridy++;
            gbc.gridx = 1;
            add(new JTextField(10), gbc);
            gbc.gridx += 2;
            add(new JTextField(10), gbc);

            gbc.gridx = 0;
            gbc.gridy++;
            gbc.anchor = GridBagConstraints.EAST;
            gbc.weightx = 0;
            gbc.fill = GridBagConstraints.NONE;
            add(new JLabel("Format:"), gbc);

            gbc.anchor = GridBagConstraints.WEST;
            gbc.gridx++;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(new JComboBox(), gbc);            
        }        
    }

    protected class EMailPane    extends JPanel {

        public EMailPane() {
            JPanel detailsPane = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.EAST;
            detailsPane.add(new JLabel("E-Mail Address:"), gbc);

            gbc.gridx++;
            gbc.anchor = GridBagConstraints.WEST;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            detailsPane.add(new JTextField(10), gbc);

            gbc.gridy++;
            gbc.gridx = 0;
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weighty = 1;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            detailsPane.add(new JScrollPane(new JList()), gbc);

            JPanel buttonsPane = new JPanel(new GridBagLayout());
            gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            buttonsPane.add(new JButton("Add"), gbc);
            gbc.gridy++;
            buttonsPane.add(new JButton("Edit"), gbc);
            gbc.gridy++;
            buttonsPane.add(new JButton("Delete"), gbc);

            gbc.gridy++;
            gbc.weighty = 1;
            gbc.anchor = GridBagConstraints.NORTH;
            buttonsPane.add(new JButton("As Default"), gbc);

            JPanel formatPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
            formatPane.setBorder(new TitledBorder(new EmptyBorder(1, 1, 1, 1), "Mail Format:"));
            formatPane.add(new JRadioButton("HTML"));
            formatPane.add(new JRadioButton("Plain"));
            formatPane.add(new JRadioButton("Custom"));

            setLayout(new BorderLayout());
            add(detailsPane);
            add(buttonsPane, BorderLayout.LINE_END);
            add(formatPane, BorderLayout.PAGE_END);                
        }            
    }        
}
于 2012-11-05T20:52:53.713 回答
2

我的首选是 MigLayout,因为它是 Swing 中最完整且文档最齐全的布局管理器。除了 Swing,它还支持 SWT 和 JavaFX,所以你花在学习上的时间可能会得到不止一次的回报。它支持maven,详情请参考http://www.miglayout.com,这是一个很大的优势。它还有一个非常有用的调试功能。您可以在构造函数中添加“调试 1”,然后您将了解如何创建布局。例子:

emailButtonPanel.setLayout(new MigLayout("wrap, fill, insets 20 10 0 10, debug 1"));

我不时发现非常有用的另一个功能是隐藏模式,它允许您在不可见的情况下不参与布局(或其他几种策略)。

这是您发布的图像的一种可能方法,使用 MigLayout:

使用 MigLayout 进行布局

import java.awt.*;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

import net.miginfocom.layout.CC;
import net.miginfocom.swing.MigLayout;

/**
 */
public class LayoutApproach {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Contact information");
                frame.getContentPane().add(new ContactPanel());
                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                frame.setMinimumSize(new Dimension(800, 450));
                frame.setLocationRelativeTo(null); // Center
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    static class ContactPanel extends JPanel {

        private JPanel namePanel;
        private TitledBorder nameTitledBorder;
        private JLabel firstNameLabel;
        private JTextField firstNameTextField;

        private JLabel lastNameLabel;
        private JTextField lastNameTextField;

        private JLabel titleLabel;
        private JTextField titleTextField;

        private JLabel nicknameLabel;
        private JTextField nickNameTextField;

        private JLabel formatLabel;
        private JComboBox<String> formatComboBox;

        private JPanel emailPanel;
        private TitledBorder emailTitledBorder;
        private JLabel emailLabel;
        private JTextField emailTextField;
        private JList<String> emailItemsList;
        private JLabel mailFormatLabel;
        private JPanel emailButtonPanel;
        private JButton addButton;
        private JButton editButton;
        private JButton removeButton;
        private JButton asDefaultButton;

        private JRadioButton htmlRadioButton;
        private JRadioButton plainTextRadioButton;
        private JRadioButton customTextRadioButton;

        private JPanel buttonPanel;

        private JButton okButton;
        private JButton cancelButton;

        public ContactPanel() {
            createComponents();
            makeLayout();
            createHandlers();
            registerHandlers();
            initComponent();
            i18n();
        }

        /**
         * Create GUI components, but contains no layout.
         */
        public void createComponents() {

            namePanel = new JPanel();
            nameTitledBorder = new TitledBorder("");
            firstNameLabel = new JLabel();
            firstNameTextField = new JTextField();
            lastNameLabel = new JLabel();
            lastNameTextField = new JTextField();
            titleLabel = new JLabel();
            titleTextField = new JTextField();
            nicknameLabel = new JLabel();
            nickNameTextField = new JTextField();
            formatLabel = new JLabel();
            formatComboBox = new JComboBox<>();

            emailPanel = new JPanel();
            emailTitledBorder = new TitledBorder("");
            emailLabel = new JLabel();
            emailTextField = new JTextField();
            emailItemsList = new JList<>();
            mailFormatLabel = new JLabel();
            emailButtonPanel = new JPanel();
            addButton = new JButton();
            editButton = new JButton();
            removeButton = new JButton();
            asDefaultButton = new JButton();

            htmlRadioButton = new JRadioButton();
            plainTextRadioButton = new JRadioButton();
            customTextRadioButton = new JRadioButton();

            buttonPanel = new JPanel();
            okButton = new JButton();
            cancelButton = new JButton("Cancel");
        }

        /**
         * Create listeners/handlers
         */
        public void createHandlers() {
        }

        /**
         * Registers/adds listeners/handlers.
         */
        public void registerHandlers() {
        }

        public void makeLayout() {
            layoutNamePanel();
            layoutEmailPanel();
            layoutButtonPanel();

            MigLayout migLayout = new MigLayout("fill, insets 20");
            setLayout(migLayout);
            add(namePanel, "dock north");
            add(emailPanel, "dock north");
            add(buttonPanel, "dock south");
        }

        private void layoutButtonPanel() {
            buttonPanel.setLayout(new MigLayout("alignX right"));
            buttonPanel.add(okButton, "tag ok");
            buttonPanel.add(cancelButton, "tag cancel");
        }

        private void layoutNamePanel() {
            MigLayout nameLayout = new MigLayout("fill, wrap 4",               // Layout Constraints
                                                 "15[]15[grow]15[]15[grow]",   // Column constraints
                                                 "");                          // Row constraints

            // -- Layout all components with name
            namePanel.setLayout(nameLayout);
            // Create this border here since I use it for layout
            Border nameBorder = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10, 6, 10, 6), nameTitledBorder);
            namePanel.setBorder(nameBorder);
            namePanel.add(firstNameLabel, "alignX right");
            namePanel.add(firstNameTextField, "grow");
            namePanel.add(lastNameLabel, "alignX right");
            namePanel.add(lastNameTextField, "grow");

            namePanel.add(titleLabel, "alignX right");
            namePanel.add(titleTextField, "grow");
            namePanel.add(nicknameLabel, "alignX right");
            namePanel.add(nickNameTextField, "grow");

            namePanel.add(formatLabel, "alignX right");
            namePanel.add(formatComboBox, new CC().grow().span(3));  // Alternative to using plain text'
        }

        private void layoutEmailPanel() {
            MigLayout emailLayout = new MigLayout("fill",// Layout Constraints
                                                  "",    // Column constraints
                                                  "");   // Row constraints

            // -- Layout all components with name
            emailPanel.setLayout(emailLayout);
            // Create this border here since I use it for layout
            Border emailBorder = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10, 6, 10, 6), emailTitledBorder);
            emailPanel.setBorder(emailBorder);

            emailButtonPanel.setLayout(new MigLayout("wrap, fill, insets 20 10 0 10"));
            emailButtonPanel.add(addButton, "growx");
            emailButtonPanel.add(editButton, "growx");
            emailButtonPanel.add(removeButton, "growx");
            emailButtonPanel.add(asDefaultButton, "growx");

            JPanel emailAndItems = new JPanel(new MigLayout("fill"));
            emailAndItems.add(emailLabel, "split 2");
            emailAndItems.add(emailTextField, "span, growx, wrap");
            emailAndItems.add(emailItemsList, "span, grow");

            JPanel radioButtons = new JPanel(new MigLayout());
            radioButtons.add(htmlRadioButton);
            radioButtons.add(plainTextRadioButton);
            radioButtons.add(customTextRadioButton);

            emailPanel.add(radioButtons, "dock south");
            emailPanel.add(mailFormatLabel, "dock south, gapleft 15");
            emailPanel.add(emailAndItems, "dock west, growx, push");
            emailPanel.add(emailButtonPanel, "dock east, shrink");

            ButtonGroup buttonGroup = new ButtonGroup();
            buttonGroup.add(htmlRadioButton);
            buttonGroup.add(plainTextRadioButton);
            buttonGroup.add(customTextRadioButton);
        }

        /**
         * Sets initial values for component.
         */
        public void initComponent() {
            formatComboBox.addItem("Item 1");
            formatComboBox.addItem("Item 2");
            formatComboBox.addItem("Item 3");
            formatComboBox.addItem("Item 4");

            DefaultListModel<String> model = new DefaultListModel<>();
            emailItemsList.setModel(model);
            model.insertElementAt("Item 1", 0);
            model.insertElementAt("Item 2", 1);
            model.insertElementAt("Item 3", 2);
            model.insertElementAt("Item 4", 3);

            customTextRadioButton.setSelected(true);
        }

        public void i18n() {
            nameTitledBorder.setTitle("Name:");
            firstNameLabel.setText("First Name:");
            lastNameLabel.setText("Last Name:");
            titleLabel.setText("Title:");
            nicknameLabel.setText("Nickname:");
            formatLabel.setText("Format:");

            emailTitledBorder.setTitle("E-mail");
            emailLabel.setText("E-mail address:");
            mailFormatLabel.setText("Mail Format:");
            addButton.setText("Add");
            editButton.setText("Edit");
            removeButton.setText("Remove");
            asDefaultButton.setText("As Default");

            htmlRadioButton.setText("HTML");
            plainTextRadioButton.setText("Plain Text");
            customTextRadioButton.setText("Custom");

            okButton.setText("OK");
            cancelButton.setText("Cancel");
        }
    }
}

该代码是用 Java 7 编写的。与之配套的 maven pom.xml 文件可能是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>stackoverflow</groupId>
    <artifactId>stackoverflow</artifactId>
    <version>1.0</version>


    <dependencies>
        <dependency>
            <groupId>com.miglayout</groupId>
            <artifactId>miglayout-core</artifactId>
            <version>4.2</version>
        </dependency>

        <dependency>
            <groupId>com.miglayout</groupId>
            <artifactId>miglayout-swing</artifactId>
            <version>4.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>
于 2012-11-06T11:00:07.673 回答
1

如果您正在寻找 Java 库布局管理器,我会说边框布局对您来说没问题。更高级的是米格布局。你可以谷歌它的信息。

你知道你可以嵌套布局管理器吗?例如,一个JPanel有一个布局管理器,另一个有一个不同的布局管理器。所以可以有边框布局和另一种流布局。

于 2012-11-05T19:32:22.433 回答
0

如果您想要一个简单的 Swing 设计器,您可以尝试 NetBeans,但恕我直言,Miglayout 是按照您的预期完成 UI 的最短方法。当然,在最初的学习曲线之后......

尝试在网格中可视化您的屏幕,然后您可以同时使用 gridbag 和 miglayout。

于 2012-11-05T19:35:03.643 回答