【问题标题】:How to place 2 JButtons at the top of a JPanel (one centered, the other topright)?如何在 JPanel 的顶部放置 2 个 JButton(一个居中,另一个位于右上角)?
【发布时间】:2017-04-18 21:58:46
【问题描述】:

我想在我的 JPanel 上放置 2 个 JButton,其中一个居中,另一个位于 JPanel 的右上角。 JPanel 与包含 JPanel 的 JFrame 大小相同。如何使用 GridBagLayout 和 GridBagConstraints 做到这一点?

public class MyPanel extends JPanel {
public MyPanel() {
    JButton btnGame1 = new JButton("Game 1");
    JButton btnExitFrame = new JButton("Exit");

    setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.anchor = GridBagConstraints.PAGE_START;
    c.weighty = 1;
    c.gridx = 0;
    add(btnGame1, c);
    c.gridx = 1;
    c.anchor = GridBagConstraints.FIRST_LINE_END;
    add(btnExitFrame, c);
}

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setResizable(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MyPanel());
    frame.setSize(400, 400);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}
}

camickr 的 MCVE

public class MyPanel extends JPanel {
static JFrame frame = new JFrame();

public MyPanel() {
    JButton btnGame1 = new JButton("Game 1");
    JButton btnExitFrame = new JButton("Exit");;

    setLayout(new BorderLayout());

    JPanel top = new JPanel( new FlowLayout(FlowLayout.RIGHT) );
    top.add( btnExitFrame );

    JPanel center = new JPanel(new GridBagLayout());
    center.add(btnGame1, new GridBagConstraints());

    add(top, BorderLayout.PAGE_START);
    add(center, BorderLayout.CENTER);
}

public static void main(String[] args) {
    frame.setResizable(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MyPanel());
    frame.setSize(400, 400);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}
}

固定 SOL'N:

public class MyPanel extends JPanel {
    static JFrame frame = new JFrame();

    public MyPanel() {
        JButton btnGame1 = new JButton("Game 1");
        JButton btnExitFrame = new JButton("Exit");;

        int nOfCells = 3;
        setLayout(new GridBagLayout());        
        GridBagConstraints c = new GridBagConstraints();
        c.weightx = 1;
        c.weighty = 1;
        for(int i = 0; i < nOfCells; i++){
            for(int j = 0; j < nOfCells; j++){
                c.gridx = i;
                c.gridy = j;               
                if(i == 1 && j == 0) {
                    c.anchor = c.PAGE_START;
                    add(btnGame1, c);
                    c.anchor = c.CENTER;
                }
                else if(i == 2 && j == 0) {
                    c.anchor = c.FIRST_LINE_END;
                    add(btnExitFrame, c);
                    c.anchor = c.CENTER;
                }
                else {
                    c.fill = c.BOTH;
                    add(Box.createRigidArea(new Dimension(frame.getWidth()/nOfCells, frame.getHeight()/nOfCells)), c);
                    c.fill = c.NONE;
                }
            }
        }

    }

    public static void main(String[] args) {
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 600);
        frame.getContentPane().add(new MyPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

image of the fixed text box

【问题讨论】:

    标签: java swing jbutton gridbaglayout


    【解决方案1】:

    另一个仅使用 GridBagLayout 的选项是添加不可见的框作为填充物,将您的 JPanel 划分为多个部分,然后用您的 JButton 替换您首选位置的框。

        GridBagConstraints c = new GridBagConstraints();
        c.weightx = 1;
        for(int i=0; i<nOfCells; i++){
            for(int k=0; k<nOfCells; k++){
    
                c.gridx = i;
                c.gridy= k;
                this.add(Box.createRigidArea(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT)), c);
            }
        }
    

    GridBagLayout 不允许在空间中固定位置,它们取决于它们相对于 JFrame 其他组件的位置。

    【讨论】:

    • 我应该将 nOfCells 定义为什么? (我有 2 个按钮可以放入框架中)
    • 嵌套的 for 循环在您的布局上创建了一个网格,每个方向都有 nOfCells 个框。您选择的数字取决于您希望 Frame 的外观,想象一下将您的 JFrame 分成定义大小的 nOfCells^2 个框,看看哪个数字可能更美观。
    • 好吧,我尝试制作 3 x 3,结果很时髦。您能否在原始响应下方粘贴一个代码块,显示您将如何编辑 MyPanel 构造函数以使“游戏 1”按钮位于 JFrame 的顶部中心,而“退出”位于右上角?
    • 好吧,在过去的 2 周里我搞砸了一点,我想我终于从你的建议中掌握了窍门。我得到了正确放置的按钮。
    【解决方案2】:

    利用框架的BorderLayout 并使用嵌套面板。

    JPanel top = new JPanel( new FlowLayout(set right alignment) ); // read FlowLayout API
    top.add( topRightButton );
    
    JPanel center = new JPanel( new GridBagLayout() );
    center.add(centerButton, new GridBagConstraints());
    
    frame.add(top, BorderLayout.PAGE_START);
    frame.add(center, BorderLayout.CENTER);
    

    编辑:

    不要使用这样的静态变量。如果您认为需要使用静态变量,那么您就有了设计问题。

    由于您将 MyPanel 类直接添加到框架中,因此您需要进行以下更改以有效地使您的 MyPanel 类成为使用 BorderLayout 的容器:

    //setLayout(new GridBagLayout());
    setLayout(new BorderLayout());
    
    ...
    
    //frame.add(top, BorderLayout.PAGE_START);
    //frame.add(center, BorderLayout.CENTER);
    add(top, BorderLayout.PAGE_START);
    add(center, BorderLayout.CENTER);
    

    我建议您也可以阅读 How to Use BorderLayout 上的 Swing 教程中的部分。那里的演示代码将展示另一种将组件直接添加到框架的方法。

    您当前的代码(加上我建议的上述更改)可能是更好的方法。但是您应该了解这两种方法,以便更好地了解布局管理器的工作原理。

    【讨论】:

    • 嗯,当我这样做时,退出按钮显示在正确的位置,但游戏 1 按钮消失了。 (我假设“设置右对齐”是FlowLayout.RIGHT)。
    • @takanuva15,如果游戏按钮没有显示你做错了什么。使用证明问题的这种方法发布您的minimal reproducible example
    • 我提出了这个问题
    • @takanuva15,我说你需要利用框架的 BorderLayout。你没有这样做。您正在将 MyPanel 类添加到框架中。这是替换“中心”面板。由于您没有向 MyPanel 类添加组件,因此在框架的 CENTER 中看不到任何内容。见编辑。
    • 酷,更好!但是,我希望 Game1 按钮位于 JFrame 的顶部中心,而不是中间中心。我将如何解决这个问题? (请参阅我对问题的编辑)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    相关资源
    最近更新 更多