如何使 JTextArea 填充宽度和 buttonsContainer 填充高度?

How to make the JTextArea fill width and buttonsContainer fill height?

我试过 GridBagLayout。它使 JTextArea 父容器占据了很大的宽度,但文本区域本身并没有填满宽度。为什么?

我希望第一个按钮靠近顶部,第二个按钮靠近底部。我该如何实施?

你能告诉我如何更正我的代码吗?

以下代码为demo全部代码

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;


public class Demo extends JFrame {

    public Demo() throws HeadlessException {
        add(new MainPanel());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }

    class MainPanel extends JPanel {
        private final InputComponent inputComponent = new InputComponent();
        private final ButtonsContainer buttons = new ButtonsContainer();

        public MainPanel() {
            setPreferredSize(new Dimension(800, 100));
            setLayout(new GridBagLayout());
            setBorder(new EmptyBorder(5, 5, 5, 5));

            add(inputComponent,
                    buildConstraints(0, 0, 1, 1, GridConstraints.FILL_BOTH, 1.0, 1.0));
            add(buttons,
                    buildConstraints(1, 0, 1, 1, GridConstraints.FILL_BOTH, 0.0, 1.0));
        }
    }

    class InputComponent extends JComponent {

        private final JTextArea textArea = new JTextArea();

        public InputComponent() {
            setLayout(new BorderLayout());

            textArea.setLineWrap(true);
            add(textArea, BorderLayout.CENTER);
        }
    }

    class ButtonsContainer extends JComponent {
        private final JButton button1 = new JButton("Button 1");
        private final JButton button2 = new JButton("Button 2");

        public ButtonsContainer() {
            setLayout(new GridBagLayout());
            add(button1, buildConstraints(0, 0, 1, 1, GridBagConstraints.HORIZONTAL, 1.0, 0.0));
            add(button2, buildConstraints(0, 1, 1, 1, GridBagConstraints.HORIZONTAL, 1.0, 0.0));
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            final Demo demo = new Demo();
        });
    }

    private GridBagConstraints buildConstraints(
            int x,
            int y,
            int gWidth,
            int gHeight,
            int fill,
            double weightX,
            double weightY
    ) {
        final GridBagConstraints constraints = new GridBagConstraints();
        constraints.gridx = x;
        constraints.gridy = y;
        constraints.gridwidth = gWidth;
        constraints.gridheight = gHeight;
        constraints.fill = fill;
        constraints.weightx = weightX;
        constraints.weighty = weightY;
        return constraints;
    }
}

如果您使用 Eclipse IDE 的 Window 生成器,您可以自动生成正确的 UI 代码: https://www.eclipse.org/windowbuilder/

以这种方式设计应用程序要容易得多。在您的 IDE 上进行设置,让它为您完成繁重的工作。如果您希望合并 UI 元素的动态调整大小,请将代码设计为 responsive.

原答案

Oracle 有一个有用的教程,Creating a GUI With Swing。跳过 Netbeans 部分。

不要使用 GUI 生成器。您最终学习了 GUI 构建器的特性,而不是学习 Java Swing。

我使用 JFrame、主 JPanel 和按钮 JPanel 创建了以下 GUI。如果您最大化 GUI,您会看到 JTextArea 展开并且 JButtons 保持在顶部和底部。

不要扩展 Swing 组件或任何其他 Java class,除非您想覆盖一个或多个 class 方法。使用组合而不是继承。

您可以使用多个简单的 JPanels 来创建复杂的 GUI。 GridBagLayout 有其用途,例如创建表单。但所需要的只是多个 BorderLayouts.

不要制作 Swing 组件 class 字段,除非您需要从不止一种方法访问字段实例。

组织您的代码,使它看起来像一篇文章,最重要的代码放在顶部,更详细的代码放在底部。理想情况下,您的代码的 reader 将永远不必向上翻页来查找内容。不,编译器不关心方法的顺序。但人类 reader 确实如此。

这是完整的可运行代码。

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class ExampleBorerLayoutGUI {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new ExampleBorerLayoutGUI();
        });
    }
    
    public ExampleBorerLayoutGUI() {
        JFrame frame = new JFrame("");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createMainPanel(), BorderLayout.CENTER);
        frame.add(createButtonPanel(), BorderLayout.EAST);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        JTextArea textArea = new JTextArea(5, 40);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        JScrollPane scrollPane = new JScrollPane(textArea);
        panel.add(scrollPane, BorderLayout.CENTER);
        
        return panel;
    }
    
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        JButton button1 = new JButton("Button 1");
        panel.add(button1, BorderLayout.NORTH);
        
        JButton button2 = new JButton("Button 2");
        panel.add(button2, BorderLayout.SOUTH);
        
        return panel;
    }

}

编辑添加

这是包含三个 JButtons 的 GUI。你没有说你想要第三个按钮在顶部还是底部。我选了顶

我为上面的按钮JPanel选择了一个GridLayout。向 GridLayout 添加更多 JButtons 很容易。

这是修改后的完整可运行代码。

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class ExampleBorderLayoutGUI {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new ExampleBorderLayoutGUI();
        });
    }
    
    public ExampleBorderLayoutGUI() {
        JFrame frame = new JFrame("Example Border Layout");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createMainPanel(), BorderLayout.CENTER);
        frame.add(createButtonPanel(), BorderLayout.EAST);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        JTextArea textArea = new JTextArea(5, 40);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        JScrollPane scrollPane = new JScrollPane(textArea);
        panel.add(scrollPane, BorderLayout.CENTER);
        
        return panel;
    }
    
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        
        panel.add(createUpperButtonPanel(), BorderLayout.NORTH);
        panel.add(createLowerButtonPanel(), BorderLayout.SOUTH);
        
        return panel;
    }
    
    private JPanel createUpperButtonPanel() {
        JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        JButton button1 = new JButton("Button 1");
        panel.add(button1);
        
        JButton button2 = new JButton("Button 2");
        panel.add(button2);
        
        return panel;
    }
    
    private JPanel createLowerButtonPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        JButton button = new JButton("Button 3");
        panel.add(button, BorderLayout.SOUTH);
        
        return panel;
    }

}