Swing GridBagLayout组件的调整大小

3
我正在开发一个项目,我的目标是使组件根据窗口的大小进行缩放。我正在使用 GridBagLayout 实现这个目标,但是当窗口大小改变时,我遇到了一些组件无法正确缩放的问题。当我给组件设置 weighty 值时,垂直方向的缩放效果非常好。http://imageshack.us/a/img211/9682/d8au.png 但是当我给组件设置 weightx 值时,所有的组件都会出现问题。按钮的大小会改变,标签之间会出现一些空隙。http://imageshack.us/a/img12/6946/ij4.png 我并没有给所有的组件都设置 weightxweighty 值,只有我需要的那些组件。由于我不是编写GUI的人,而是通过拖放组件来实现的,所以我没有任何代码。我只需要一些建议,告诉我如何修复这个问题,让组件正确地缩放。我猜测这是因为 weightx 的原因,但是我不知道如何才能使一切正常运作。

2
我建议先将用户界面分解为单独的部分,独立地布置每个部分。权重被其他列中的组件混淆了。 - MadProgrammer
2个回答

2
正如我在评论中建议的,Hovercraft也提出了同样的建议,我建议将您的UI拆分为不同的部分,分别关注每个部分的布局要求,否则您会发现为一个组件做出的决策会对其他组件产生不利影响。
我还建议在您理解布局实际操作并手动编写布局之前避免使用GUI设计师。别误会,我经常使用Netbeans表单设计器,但是当需要生成动态和变换的UI时,我也会通过手动调整许多UI。
以下示例演示了我的意思。我使用 LineBorder 标记了UI的每个部分,使其突出显示。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class BadLayout25 {

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

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

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

        });
    }

    public class BasePane extends JPanel {

        public BasePane() {
            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.gridwidth = 2;
            gbc.fill = java.awt.GridBagConstraints.HORIZONTAL;
            gbc.weightx = 1.0;
            add(getTopPane(), gbc);

            gbc = new java.awt.GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.fill = java.awt.GridBagConstraints.HORIZONTAL;
            gbc.weightx = 0.5;
            add(getOptionsPane(), gbc);

            gbc = new java.awt.GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 2;
            gbc.fill = java.awt.GridBagConstraints.BOTH;
            gbc.weightx = 0.5;
            gbc.weighty = 1.0;
            add(getButtonPane(), gbc);

            JTextArea textArea = new JTextArea(5, 20);

            gbc = new java.awt.GridBagConstraints();
            gbc.gridx = 1;
            gbc.gridy = 1;
            gbc.gridheight = 2;
            gbc.fill = java.awt.GridBagConstraints.BOTH;
            gbc.weightx = 0.5;
            gbc.weighty = 1.0;
            add(new JScrollPane(textArea), gbc);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(800, 400);
        }

        protected JPanel getTopPane() {
            JPanel topPane = new JPanel(new GridBagLayout());
            topPane.setBorder(BorderFactory.createLineBorder(java.awt.Color.RED));
            topPane.add(new JLabel("Lotereya:"));
            topPane.add(new JLabel("Yuklenilir"));
            return topPane;
        }

        protected JPanel getOptionsPane() {
            JPanel optionsPane = new JPanel(new GridBagLayout());
            optionsPane.setBorder(BorderFactory.createLineBorder(new java.awt.Color(0, 255, 0)));
            GridBagConstraints gbc = new GridBagConstraints();

            gbc = new GridBagConstraints();
            gbc.anchor = java.awt.GridBagConstraints.LINE_START;
            optionsPane.add(new JLabel("Tiraj nomre:"), gbc);

            gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.gridwidth = 2;
            gbc.anchor = java.awt.GridBagConstraints.LINE_START;
            optionsPane.add(new JLabel("Sablon nomresi:"), gbc);

            JTextField field = new JTextField(10);
            gbc = new GridBagConstraints();
            gbc.gridx = 2;
            gbc.gridy = 1;
            gbc.anchor = java.awt.GridBagConstraints.LINE_START;
            gbc.weightx = 1.0;
            optionsPane.add(field, gbc);

            JComboBox comboBox = new JComboBox();
            gbc = new GridBagConstraints();
            gbc.gridx = 1;
            gbc.gridy = 0;
            gbc.gridwidth = 2;
            gbc.anchor = java.awt.GridBagConstraints.LINE_START;
            gbc.weightx = 1.0;
            optionsPane.add(comboBox, gbc);

            return optionsPane;
        }

        protected JPanel getButtonPane() {
            JPanel buttonsPane = new JPanel(new GridBagLayout());
            buttonsPane.setBorder(BorderFactory.createLineBorder(new java.awt.Color(0, 0, 255)));

            GridBagConstraints gbc = new GridBagConstraints();
            gbc = new java.awt.GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = -1;
            gbc.fill = java.awt.GridBagConstraints.BOTH;
            gbc.weightx = 0.25;
            gbc.weighty = 0.25;
            for (int index = 0; index < 9; index++) {
                if (index % 3 == 0) {
                    gbc.gridy++;
                    gbc.gridx = 0;
                } else {
                    gbc.gridx++;
                }
                buttonsPane.add(new JButton(String.valueOf(index + 1)), gbc);
            }
            gbc = new GridBagConstraints();
            gbc.gridx = 1;
            gbc.gridy = 3;
            gbc.fill = java.awt.GridBagConstraints.BOTH;
            gbc.weightx = 0.25;
            gbc.weighty = 0.25;
            buttonsPane.add(new JButton("0"), gbc);

            gbc = new GridBagConstraints();
            gbc.gridx = 3;
            gbc.gridy = 0;
            gbc.fill = java.awt.GridBagConstraints.BOTH;
            gbc.weightx = 0.25;
            gbc.weighty = 0.25;
            buttonsPane.add(new JButton("Tesdiq"), gbc);
            gbc.gridy++;
            buttonsPane.add(new JButton("<ticket.apply>"), gbc);
            gbc.gridy++;
            buttonsPane.add(new JButton("<ticket.cancel>"), gbc);
            gbc.gridy++;
            buttonsPane.add(new JButton("<main menu>"), gbc);

            return buttonsPane;
        }
    }
}

2
首先,不要像本站的某些人建议的那样使用 null 布局。新手常常会建议使用 null 布局,因为表面上和最初看起来它确实更容易使用,但是后来你会发现所有的问题,包括在尝试在不同平台上运行应用程序时出现的丑陋或无法正常工作的 GUI,以及如果想要修改 GUI 中的任何内容所需的极大困难,因为这需要手动修改所有其他组件,这些组件位于修改的组件的右侧或下方。使用布局管理器的美妙之处在于它允许它们为您完成艰苦的工作,使维护和升级变得轻而易举。
我建议嵌套具有嵌套布局的 JPanel。例如,计算器按钮的行为就像是一个固定网格,因此对于它们使用 GridLayout,并在底部没有按钮的地方使用 JLabel 占位符。
外部 GUI JPanel 可以使用 GridBagLayout(如果需要),或者您可以轻松混合使用其他更容易的布局。

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