【问题标题】:How to make the JTextArea fill width and buttonsContainer fill height?如何让 JTextArea 填充宽度和buttonsContainer 填充高度?
【发布时间】:2022-01-20 01:53:36
【问题描述】:

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

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

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

以下代码是演示的全部代码。

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

【问题讨论】:

    标签: java swing jbutton layout-manager jtextarea


    【解决方案1】:

    原答案

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

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

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

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

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

    除非您需要从多个方法访问字段实例,否则不要将 Swing 组件类设为字段。

    组织您的代码,使其读起来像一篇文章,最重要的代码在顶部,更详细的代码在底部。理想情况下,您的代码的读者将永远不必翻页来查找某些内容。不,编译器不关心方法的顺序。但人类读者肯定会。

    这是完整的可运行代码。

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

    【讨论】:

    • 谢谢。当在东按钮面板中添加 3 个按钮时,您能否建议如何实现相同的效果?仍然使用 BorderLayout 并使第二个按钮位于 Center 将导致第二个按钮占据更多高度。谢谢
    • @ildvzg68472:查看更新后的答案。
    • 谢谢!所以有必要先评估一下。是否有任何 LayoutManager 像 CSS 中的 flex 中的“justify-content: space-between”一样工作,开发人员只需要添加新元素,它就会尊重元素的首选大小并帮助在它们之间安排相同的空间?谢谢
    • @ildvzg68472:Swing 不是 CSS。您必须以完全不同的方式创建 GUI。一般来说,你做我做的事。 1)设计整个GUI。 2) 根据需要将 GUI 分解为多个JPanels。 3)编码每个JPanel
    【解决方案2】:

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

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

    【讨论】:

    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center