如何在Java Swing中编写此GUI程序

3

我正在开发一个带有以下GUI的小型实用程序:

样例GUI

现在,我有一个使用BorderLayout布局的容器(JPanel),它将一切放在原处。然后,我又有另外两个JPanel分别放置在BorderLayout.NORTH和BorderLayout.SOUTH上,每个面板都采用GridLayout(2列1行)。表格位于主容器的中央。

您认为这是最好的方法吗?我在处理组件之间的间距和框架边框时遇到了麻烦。

现在我有这段代码:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.SwingUtilities;

public class GUI extends JFrame {

    private JButton loadFileBtn = new JButton("Load File");
    private JButton generateReportBtn = new JButton("Generate Report");
    private JButton exitBtn = new JButton("Exit");
    private JLabel fileNameLbl = new JLabel("File Name Here");
    private JMenuBar menuBar = new JMenuBar();
    private JMenu fileMI = new JMenu("File");
    private JMenuItem openFileMenu = new JMenuItem("Open File");
    private JSeparator separator = new JSeparator();
    private JMenuItem exitMenu = new JMenuItem("Exit");
    private JMenu reportMI = new JMenu("Report");
    private JMenuItem generateReportMenu = new JMenuItem("Generate Report");
    private JMenu helpMI = new JMenu("Help");
    private JMenuItem aboutMenu = new JMenuItem("About");
    private JTable table = new JTable(5, 2);
    private JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
    private JPanel panel1 = new JPanel(new BorderLayout());
    private JPanel panel2 = new JPanel(new GridLayout(1, 2));
    private JPanel panel3 = new JPanel(new GridLayout(1, 2));

    public GUI() {

        super("Sample GUI");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(new Dimension(300, 300));
        setResizable(false);

        setLayout(new BorderLayout(10, 10));

        fileMI.add(openFileMenu);
        fileMI.add(separator);
        fileMI.add(exitMenu);

        reportMI.add(generateReportMenu);

        helpMI.add(aboutMenu);

        menuBar.add(fileMI);
        menuBar.add(reportMI);
        menuBar.add(helpMI);

        setJMenuBar(menuBar);

        panel1.add(table, BorderLayout.CENTER);

        panel2.add(fileNameLbl);
        panel2.add(loadFileBtn);

        panel3.add(generateReportBtn);
        panel3.add(exitBtn);

        mainPanel.add(panel2, BorderLayout.NORTH);
        mainPanel.add(panel1, BorderLayout.CENTER);
        mainPanel.add(panel3, BorderLayout.SOUTH);

        add(mainPanel);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GUI app = new GUI();
                app.setVisible(true);
            }
        });
    }
}

你认为最好的方法是什么?

非常感谢任何帮助。


更新:

现在,我有以下GUI

enter image description here

我希望组件能够平均地远离边框,就像模型中一样。


你的问题是什么?你想要引入哪个空间并且出现了什么问题?你可以随时使用BorderFactory.createEmptyBorder(int, int, int, int) - Guillaume Polet
@Guillaume Polet 不确定,请不要攻击,您是指使用 EmptyBorder 来避免使用 setPreferredSize,还是使用 EmptyBorder 来避免在 NestedLayout 表单中使用 SpringLayoutGridBagLayout,还是使用 MigLayout 等等。 - mKorbel
@mKorbel 空边框是一种非常简单(有时也很优雅)的解决方案,可以在不必切换到另一个 LayoutManager 的情况下,在容器中正确定位组件。如果 OP 对这些 LayoutManager 感到舒适,空边框可能是解决他实际问题的好方法。 - Guillaume Polet
4个回答

4

过去,我发现使用MigLayout解决了我的所有问题。


1
是的,MigLayout 几乎总是我选择的方式。学起来相当容易,使用起来也非常简单。 - wchargin
不知道这个。谢谢,我会去查一下的。 - DaveQuinn

4

您可以使用以下两种方法来实现此操作:

  1. 使用BorderFactory.createEmptyBorder(int, int, int, int)
  2. 使用GridLayout的4个参数构造函数

还有其他的LayoutManager可以提供同样的功能(例如GridBagLayout或使用嵌套的BorderLayout),但是如果您对当前的LayoutManager感到满意,就没有必要改变它们。您所做的方法也是可接受的。

enter image description here

您可能考虑将表格包装在JScrollPane中,以使其更美观,并具备标题和滚动条(如果需要)。

简单的示例代码:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.SwingUtilities;

public class GUI extends JFrame {

    private JButton loadFileBtn = new JButton("Load File");
    private JButton generateReportBtn = new JButton("Generate Report");
    private JButton exitBtn = new JButton("Exit");
    private JLabel fileNameLbl = new JLabel("File Name Here");
    private JMenuBar menuBar = new JMenuBar();
    private JMenu fileMI = new JMenu("File");
    private JMenuItem openFileMenu = new JMenuItem("Open File");
    private JSeparator separator = new JSeparator();
    private JMenuItem exitMenu = new JMenuItem("Exit");
    private JMenu reportMI = new JMenu("Report");
    private JMenuItem generateReportMenu = new JMenuItem("Generate Report");
    private JMenu helpMI = new JMenu("Help");
    private JMenuItem aboutMenu = new JMenuItem("About");
    private JTable table = new JTable(5, 2);
    private JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
    private JPanel panel1 = new JPanel(new BorderLayout());
    private JPanel panel2 = new JPanel(new GridLayout(1, 2, 10, 10));
    private JPanel panel3 = new JPanel(new GridLayout(1, 2, 10, 10));

    public GUI() {

        super("Sample GUI");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(new Dimension(300, 300));
        setResizable(false);

        setLayout(new BorderLayout(10, 10));

        fileMI.add(openFileMenu);
        fileMI.add(separator);
        fileMI.add(exitMenu);

        reportMI.add(generateReportMenu);

        helpMI.add(aboutMenu);

        menuBar.add(fileMI);
        menuBar.add(reportMI);
        menuBar.add(helpMI);

        setJMenuBar(menuBar);

        panel1.add(table, BorderLayout.CENTER);

        panel2.add(fileNameLbl);
        panel2.add(loadFileBtn);

        panel3.add(generateReportBtn);
        panel3.add(exitBtn);

        mainPanel.add(panel2, BorderLayout.NORTH);
        mainPanel.add(panel1, BorderLayout.CENTER);
        mainPanel.add(panel3, BorderLayout.SOUTH);
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        add(mainPanel);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GUI app = new GUI();
                app.setVisible(true);
            }
        });
    }
}

@mKorbel你建议在JFrame的西、东、北和南方添加一个强制优先大小的空JPanel吗? - Guillaume Polet
像@Gilbert Le Blanc建议的那样,使用FlowLayout而不是GridLayout应该更加灵活,可以让我在北边的标签和按钮之间以及南部区域的两个按钮之间创建间隙。你的意见是什么? - DaveQuinn
@PMMP 取决于您想要实现什么。如果您喜欢按钮“等大小”,则 GridLayout 是最好的选择。如果您希望每个按钮都有自己的大小并以某种方式对齐,则 FlowLayoutBoxLayout 是更好的选择。没有正确或错误的 LayoutManager,只有适合特定需求/愿望的 LayoutManager - Guillaume Polet
@Guillaume Polet 这个间隙是在顶层容器、边框布局、空 JPanel 中自动创建的,不需要任何大小,由 BorderLayout 完成。 - mKorbel
1
@mKorbel,好的,现在我明白你的意思了。如果我添加空的JPanels,则BorderLayout的hGap和vGap将会生效,并自动出现一个空边框。就我个人而言,我仍然更喜欢明确创建空边框,以实现所描述的效果。色彩和口味总是可以争论的....;-) - Guillaume Polet
显示剩余2条评论

3
这是我安排GUI的方式,这只是其中一种方式,不是唯一的方式。
  • JTable置于JScrollPane内。

  • Button2Button3置于带有FlowLayout的按钮JPanel内。

  • LabelButton1置于带有FlowLayout的标签JPanel内。

  • 文件、报告和帮助是JMenuBar上的JMenuItem

  • JPanel具有Y轴方向的BoxLayout

  • 将标签JPanelJScrollPane和按钮JPanel添加到主JPanel中。


会尝试联系 @Gilbert Le Blanc。感谢您的意见,非常感激。 - DaveQuinn

2
创建GUI的最佳方式是以你和其他人都能理解的方式编码。请参阅此《布局管理器指南》(Guide to Layout Managers)。您可以为不同组件使用不同的布局管理器。这将有助于设置正确的间距。
如果您的问题只是围绕组件周围的间距,请设置其Insets

你推荐哪些布局管理器适用于这个设计?这是我提问的动机。 - DaveQuinn
在我看来,GridBagLayout 是最灵活的。但也许我会混合使用一些布局管理器。在顶部和底部放置一个面板,在中间放置表格,并使用 BorderLayout。底部的面板我会使用 FlowLayout,而顶部的面板可能是 FlowLayout 或 GridBagLayout。或者用 GridBagLayout 来完成所有的布局(需要大量编码)。 - Jean Waghetti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接