如何使用默认 FlowLayout 在 JPanel 中将 JButton 居中?

Posted

技术标签:

【中文标题】如何使用默认 FlowLayout 在 JPanel 中将 JButton 居中?【英文标题】:How can I center a JButton in a JPanel using the default FlowLayout? 【发布时间】:2021-10-05 12:03:23 【问题描述】:

我正在尝试使用默认 FlowLayout 在 JPanel 中将 JButton 居中。这是我的代码:

import javax.swing.*;
import java.awt.*;
public class CoinFlip 
    public static void main(String[] args) 
        JFrame frame = new JFrame("Coin Flip");
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton coinFlipButton = new JButton("Flip Coin");
        coinFlipButton.setSize(100, 100);
        JPanel coinFlipPanel = new JPanel();
        coinFlipPanel.setSize(500, 100);
        coinFlipPanel.setBackground(Color.GRAY);
        coinFlipPanel.add(coinFlipButton);
        JTextArea coinFlipResults = new JTextArea();
        coinFlipResults.setSize(500, 200);
        frame.getContentPane().add(coinFlipPanel);
        frame.getContentPane().add(coinFlipResults);
        frame.setVisible(true);
    

如何在 JPanel (coinFlipPanel) 中将 JButton (coinFlipButton) 居中?我试过使用 FlowLayout.CENTER 但这会使按钮的大小增加,从而占用所有空间。

【问题讨论】:

这段代码似乎没有意义。如果您像这样向 JFrame 添加两个组件,那么您将它们都添加到同一个区域并且 JFrame 应该只显示一个(因为它的布局 BorderLayout 就是这样工作的)。并且尝试将 FlowLayout 居中对我个人来说没有意义。试着告诉我们你想做什么,我们会尽力想出一些可行的方法。 您的问题不完整。您有两个组件,并且没有为每个组件指定要求。您希望组件在同一行上还是垂直显示或其他排列?另外,不要使用 setSize(...)。它什么也不做。布局管理器会根据布局管理器的规则确定每个组件的大小。 参见this answer 了解使组件居中的四种方法。我通常不希望组件拉伸到容器(面板)的大小,因此请避免左侧的两个。我更喜欢GridBagLayout(右上角)而不是BoxLayout.. 一般提示: 1) 请参阅Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?(是的。)该建议也适用于setSize()。有多种方法可以使按钮变大。 .. .. 2) 以最小尺寸提供 ASCII 艺术或 GUI 的 预期 布局的简单绘图,如果可调整大小,则具有更大的宽度和高度 - 以展示如何应该使用额外的空间。 【参考方案1】:

我仔细检查了文档,FlowLayout 确实可以选择将其组件居中,所以这是罪魁祸首。但除此之外,您只需阅读有关各种组件及其布局的教程,并进行一些实验。

非常重要的一点是jframe.getContentPane().add() 对于默认 JFrame 使用的布局只允许一个组件。如果您想要多个,则必须使用第二个组件,例如具有 Grid 或 Flow 布局的 JPanel。通过两次调用该方法,您只是替换了以前的组件。请阅读有关 JFrames 和 BorderLayout 的教程。

无论如何,我制作了一个快速程序,可以执行您想要的操作。我将您的文本区域添加到 ScrollPane,因为这是处理 JFrame 的主要内容窗格的另一种方式。当我使用按钮添加 JPanel 时,我将它添加到 BorderLayout 的 SOUTH 部分,因为这就是您使用 BorderLayout 显示多个组件的方式。 (又是教程。)

public class JFrameBorderWithButton 
   public static void main( String[] args ) 
      SwingUtilities.invokeLater( JFrameBorderWithButton::newGui );
   
   private static void newGui() 
      JFrame frame = new JFrame();
      
      JTextArea text = new JTextArea(5, 40);
      JScrollPane scroll = new JScrollPane( text );
      frame.add( scroll );
      JPanel panel = new JPanel( new FlowLayout( FlowLayout.CENTER ) );
      JButton button = new JButton( "Press Me" );
      panel.add(  button );
      frame.add( panel, BorderLayout.SOUTH );
      
      frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      frame.pack();
      frame.setLocationRelativeTo( null );
      frame.setVisible( true );
   

【讨论】:

“FlowLayout 确实可以选择将其组件居中” 水平,是的。对于水平垂直居中,使用GridBagLayout 谢谢,我对 GridBag 不是很熟悉,不知道。【参考方案2】:

根据我的经验,简单的布局很少值得。使用类似 GridBagLayout 的东西

public static void main(String [] args) throws IOException 
    JFrame frame = new JFrame("Coin Flip");
    JTextArea textArea = new JTextArea();
    JScrollPane textScroll = new JScrollPane(textArea);
    Action flipAction = new AbstractAction("Flip Coin!") 
        private Random random = new Random();
        
        @Override
        public void actionPerformed(ActionEvent e) 
            if (!textArea.getText().isEmpty()) 
                textArea.append(System.lineSeparator());
            
            
            if (random.nextBoolean()) 
                textArea.append("Heads!");
             else 
                textArea.append("Tails!");
            
        
    ;
            
    JButton flipButton = new JButton(flipAction);
    
    frame.setLayout(new GridBagLayout());
    frame.setPreferredSize(new Dimension(175, 500));
    frame.add(flipButton, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 0));
    frame.add(textScroll, new GridBagConstraints(0, 1, 1, 3, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(4, 4, 4, 4), 0, 0));
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

【讨论】:

简单的布局很少值得 - 往往会不同意。如果使用得当,它们很方便。例如,工具栏的 FlowLayout 或网格的 GridLayout。 GridBagLayout 可能过于复杂,尤其是当您使用上述代码时。大多数人不知道所有 9 个参数的顺序以及它们的含义。事实上,3 的“gridheight”没有任何作用,因为您可以随机分配一个组件来占用 3 个单元格。此外,OP 希望按钮居中,因此使用水平填充默认目的 "简单的布局很少值得使用。使用类似 GridBagLayout" 这听起来好像你不熟悉 组合 布局。将它们组合起来是创建复杂、强大的 GUI 的最简单方法。一个例子请参见this answer。 我写 Swing 已经将近 15 年了。组合布局表明您不知道如何使用更复杂的布局。 GridBagLayout 和 MiGLayout 是迄今为止更有用的布局。我唯一见过嵌入式布局是在向屏幕添加页眉和页脚时。

以上是关于如何使用默认 FlowLayout 在 JPanel 中将 JButton 居中?的主要内容,如果未能解决你的问题,请参考以下文章

FlowLayout 的意外行为

如何手动使用 FlowLayout 中的estimateSize

10.4 使用布局管理器1(FlowLayout)

如何使用 FlowLayout 确定 UICollectionView 的高度

IDEA插件开发,Jpane中集成Web页面

Java基础入门-第八章-04