Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在GridBagLayout中垂直对齐不同大小的按钮?_Java_Swing_Center_Layout Manager_Gridbaglayout - Fatal编程技术网

Java 如何在GridBagLayout中垂直对齐不同大小的按钮?

Java 如何在GridBagLayout中垂直对齐不同大小的按钮?,java,swing,center,layout-manager,gridbaglayout,Java,Swing,Center,Layout Manager,Gridbaglayout,我从swing开始,我有一些关于如何在GridBagLayout中对齐元素的问题,我也不确定这是否是正确的方法,请给出建议 我有下面的代码 import javax.swing.*; import java.awt.*; public class App { public void start() { JPanel mainPanel = new JPanel(new FlowLayout()); mainPanel.setBorder(BorderFa

我从swing开始,我有一些关于如何在GridBagLayout中对齐元素的问题,我也不确定这是否是正确的方法,请给出建议

我有下面的代码

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

public class App {
    public void start() {
        JPanel mainPanel = new JPanel(new FlowLayout());
        mainPanel.setBorder(BorderFactory.createLineBorder(Color.CYAN, 20));

        //buttons for initial options
        JButton button1 = new JButton("This is option A");
        JButton button2 = new JButton("option B");
        JButton button3 = new JButton("Another text");

        JPanel second = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.CENTER;
        second.setBackground(Color.GREEN);
        second.add(button1, gbc);
        second.add(button2, gbc);
        second.add(button3, gbc);

        mainPanel.add(second, BorderLayout.CENTER);

        //frame configuration
        JFrame frame = new JFrame();
        frame.setContentPane(mainPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setResizable(false);
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
        SwingUtilities.invokeLater(() -> new App().start());
    }
}
我的目标是产生以下输出:

到目前为止,我已经尝试了垂直对齐的BoxLayout,但问题是它覆盖了按钮的首选大小,我希望它们都是相同的宽度

此外,我还尝试使用GridLayout和BorderLayout将元素添加到北部、中部和南部,但按钮的大小会发生变化

建议采用什么方法使元素居中,但保持其尺寸?我想嵌套布局:

  • 容纳按钮并使用
    新网格布局(0,1,0,vGap)
    的JPanel——容纳一列和可变行数的网格,按钮之间有vGap
  • 将该JPanel添加到另一个使用GridBagLayout的JPanel中,并以默认方式(无GridBagConstraints)将其添加到第二个JPanel的中心。这显然必须是所需的尺寸。这可以通过以下两种方式实现:
    • 以合理的方式重写
      getPreferredSize()
    • 调用
      setPreferredSize(新维度(someWidth,someHeight))
      ——这并不是很“干净”
    • 给它一个边框,特别是一个
      BorderFactor.EmptyBorder(gap,gap,gap,gap)
      其中gap是JPanel周围边框的大小
    完成了

    使用GridBagLayout的测试代码:

    import java.awt.Dimension;
    import java.awt.GridBagLayout;
    import java.awt.GridLayout;
    import javax.swing.*;
    
    public class ButtonLayout extends JPanel {
        public static final int MY_WIDTH = 750;
        public static final int MY_HEIGHT = 500;
        private static final float BTN_SIZE = 24f;
        
        private String[] buttonTexts = {"This is Option A", "Option B", 
                "Something Else Entirely"};
        
        public ButtonLayout() {
            int colGap = 20;
            JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 0, colGap));
            for (String btnText : buttonTexts) {
                JButton button = new JButton(btnText);
                
                // set first letter of text as mnemonic (alt-char shortcut)
                int mnemonic = (int) btnText.charAt(0);
                button.setMnemonic(mnemonic);
                
                // make button bigger by increasing its font
                button.setFont(button.getFont().deriveFont(BTN_SIZE));
                
                // add to the GridLayout-using JPanel
                buttonPanel.add(button);
            }
            
            // set layout of main panel to GridBag
            setLayout(new GridBagLayout());
            
            // add the button panel in a "default" manner (no constraints)
            // which centers this panel
            add(buttonPanel);
        }
        
        @Override
        public Dimension getPreferredSize() {
            Dimension superSize = super.getPreferredSize();
            int width = Math.max(MY_WIDTH, superSize.width);
            int height = Math.max(MY_HEIGHT, superSize.height);
            
            return new Dimension(width, height);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    
        private static void createAndShowGui() {
            ButtonLayout mainPanel = new ButtonLayout();
            JFrame frame = new JFrame("ButtonLayout");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }
    
    使用EmptyByOrder的示例2:

    import java.awt.GridLayout;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class ButtonLayout extends JPanel {
        public static final int MY_WIDTH = 750;
        public static final int MY_HEIGHT = 500;
        private static final float BTN_SIZE = 24f;
        
        private String[] buttonTexts = {"This is Option A", "Option B", 
                "Something Else Entirely"};
        
        public ButtonLayout() {
            int colGap = 20;
            JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 0, colGap));
            for (String btnText : buttonTexts) {
                JButton button = new JButton(btnText);
                
                // set first letter of text as mnemonic (alt-char shortcut)
                int mnemonic = (int) btnText.charAt(0);
                button.setMnemonic(mnemonic);
                
                // make button bigger by increasing its font
                button.setFont(button.getFont().deriveFont(BTN_SIZE));
                
                // add to the GridLayout-using JPanel
                buttonPanel.add(button);
            }
            
            add(buttonPanel);
            
            int top = 60;
            int left = top;
            int bottom = 2 * top;
            int right = left;
            setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right));
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    
        private static void createAndShowGui() {
            ButtonLayout mainPanel = new ButtonLayout();
            JFrame frame = new JFrame("ButtonLayout");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }
    
    我会:

  • 容纳按钮并使用
    新网格布局(0,1,0,vGap)
    的JPanel——容纳一列和可变行数的网格,按钮之间有vGap
  • 将该JPanel添加到另一个使用GridBagLayout的JPanel中,并以默认方式(无GridBagConstraints)将其添加到第二个JPanel的中心。这显然必须是所需的尺寸。这可以通过以下两种方式实现:
    • 以合理的方式重写
      getPreferredSize()
    • 调用
      setPreferredSize(新维度(someWidth,someHeight))
      ——这并不是很“干净”
    • 给它一个边框,特别是一个
      BorderFactor.EmptyBorder(gap,gap,gap,gap)
      其中gap是JPanel周围边框的大小
    完成了

    使用GridBagLayout的测试代码:

    import java.awt.Dimension;
    import java.awt.GridBagLayout;
    import java.awt.GridLayout;
    import javax.swing.*;
    
    public class ButtonLayout extends JPanel {
        public static final int MY_WIDTH = 750;
        public static final int MY_HEIGHT = 500;
        private static final float BTN_SIZE = 24f;
        
        private String[] buttonTexts = {"This is Option A", "Option B", 
                "Something Else Entirely"};
        
        public ButtonLayout() {
            int colGap = 20;
            JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 0, colGap));
            for (String btnText : buttonTexts) {
                JButton button = new JButton(btnText);
                
                // set first letter of text as mnemonic (alt-char shortcut)
                int mnemonic = (int) btnText.charAt(0);
                button.setMnemonic(mnemonic);
                
                // make button bigger by increasing its font
                button.setFont(button.getFont().deriveFont(BTN_SIZE));
                
                // add to the GridLayout-using JPanel
                buttonPanel.add(button);
            }
            
            // set layout of main panel to GridBag
            setLayout(new GridBagLayout());
            
            // add the button panel in a "default" manner (no constraints)
            // which centers this panel
            add(buttonPanel);
        }
        
        @Override
        public Dimension getPreferredSize() {
            Dimension superSize = super.getPreferredSize();
            int width = Math.max(MY_WIDTH, superSize.width);
            int height = Math.max(MY_HEIGHT, superSize.height);
            
            return new Dimension(width, height);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    
        private static void createAndShowGui() {
            ButtonLayout mainPanel = new ButtonLayout();
            JFrame frame = new JFrame("ButtonLayout");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }
    
    使用EmptyByOrder的示例2:

    import java.awt.GridLayout;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class ButtonLayout extends JPanel {
        public static final int MY_WIDTH = 750;
        public static final int MY_HEIGHT = 500;
        private static final float BTN_SIZE = 24f;
        
        private String[] buttonTexts = {"This is Option A", "Option B", 
                "Something Else Entirely"};
        
        public ButtonLayout() {
            int colGap = 20;
            JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 0, colGap));
            for (String btnText : buttonTexts) {
                JButton button = new JButton(btnText);
                
                // set first letter of text as mnemonic (alt-char shortcut)
                int mnemonic = (int) btnText.charAt(0);
                button.setMnemonic(mnemonic);
                
                // make button bigger by increasing its font
                button.setFont(button.getFont().deriveFont(BTN_SIZE));
                
                // add to the GridLayout-using JPanel
                buttonPanel.add(button);
            }
            
            add(buttonPanel);
            
            int top = 60;
            int left = top;
            int bottom = 2 * top;
            int right = left;
            setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right));
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    
        private static void createAndShowGui() {
            ButtonLayout mainPanel = new ButtonLayout();
            JFrame frame = new JFrame("ButtonLayout");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }
    

    我不确定我是否完全理解这个问题,但如果您希望垂直对齐按钮,但允许它们保持其首选大小,例如,不要提供任何类型的
    填充
    约束

    或者,如果希望它们具有相同的宽度,请使用
    fill
    约束

    如果你想混合一个更复杂的布局,那么你应该考虑使用复合布局

    但是等等,没有提纲。。。 因此,您可以通过多种方式“可能”做到这一点,例如,您可以使用
    CompoundBorder

    setBorder(new CompoundBorder(new LineBorder(Color.CYAN, 16), new EmptyBorder(32, 32, 32, 32)));
    


    但问题在于细节

    我不确定我是否完全理解这个问题,但如果您想垂直对齐按钮,但允许它们保持其首选大小,例如,不要提供任何类型的
    填充
    约束

    或者,如果希望它们具有相同的宽度,请使用
    fill
    约束

    如果你想混合一个更复杂的布局,那么你应该考虑使用复合布局

    但是等等,没有提纲。。。 因此,您可以通过多种方式“可能”做到这一点,例如,您可以使用
    CompoundBorder

    setBorder(new CompoundBorder(new LineBorder(Color.CYAN, 16), new EmptyBorder(32, 32, 32, 32)));
    


    但魔鬼在细节中

    @FrederickÁlvarez,读到建议在面板底部使用一个空的顺序,以便在底部留出额外的空间,使其看起来更接近顶部。收回了我的赞成票。我不喜欢为JPanel重写getPreferredSize()方法。布局管理器应该根据添加的组件和正在使用的边框来计算大小。顺便说一句-DKM-覆盖首选大小的代码是我见过的更好的实现之一-因为它考虑了“自然”首选大小。我只是觉得在这种情况下根本没有必要。1)[加上2种解决方案的1。[2)克利奥帕特拉也教会了我一件事或两千件事。@dontknowmuchbutgetting更好,我从克利奥帕特拉那里学到了艰难的道路…-是的,我们都有,我完全同意。在需要时,重写getPreferredSize()总是比使用setPreferredSize(…)更可取。我是说在这种情况下两者都不需要。您编写的自定义代码越少越好。清空顺序将允许OP使用API在按钮面板周围留出额外空间。@FrederickÁlvarez,请阅读关于使用清空顺序在面板底部留出额外空间的建议,使其看起来更接近顶部。收回我的赞成票。我不喜欢为JPanel重写getPreferredSize()方法。布局管理器应该根据添加的组件和正在使用的边框来计算大小。顺便说一句-DKM-覆盖首选大小的代码是我见过的更好的实现之一-因为它考虑了“自然”首选大小。我只是觉得在这种情况下根本没有必要。1)[加上2种解决方案的1。[2)克利奥帕特拉也教会了我一件事或两千件事。@dontknowmuchbutgetting更好,我从克利奥帕特拉那里学到了艰难的道路…-是的,我们都有,我完全同意。在需要时,重写getPreferredSize()总是比使用setPreferredSize(…)更可取。我是说在这种情况下两者都不需要。您编写的自定义代码越少越好。EmptyByOrder将允许OP使用API来提供额外的空间