【问题标题】:Centering a JLabel in a JPanel在 JPanel 中将 JLabel 居中
【发布时间】:2012-04-07 10:18:55
【问题描述】:

我有一个源自JPanel 的面板。我有一个源自JLabel 的自定义控件。我正在尝试将这个自定义 JLabel 放在我的面板上。

我知道的唯一可行的方法是使用空布局 (setLayout(null)),然后计算自定义 JLabel 的 setLocation() 点,使其位于正确的位置。

自定义JLabel 在此应用程序中从一个面板物理移动到此面板,我相信之前在setLocation 中设置的位置正在影响事物。但是,当我将其设置为 (0,0) 时,组件会上升到左上角。

BorderLayout 不起作用,因为当仅提供 1 个组件并将其放入 BorderLayout.CENTER 时,中心部分会扩展以填充所有空间。

我从另一个站点剪切和粘贴的示例使用了BoxLayoutcomponent.setAlignmentX(Component.CENTER_ALIGNMENT)。这也不起作用。

另一个答案提到覆盖面板的getInset() 函数(我认为这就是它的名称),但事实证明这是一条死胡同。

到目前为止,我正在使用具有GridBagLayout 布局的面板,当我将自定义JLabel 插入面板时,我包含了一个GridBagConstraints 对象。但是,这是低效的。有没有更好的方法让JLabel 在我的JPanel 中居中?

【问题讨论】:

  • 考虑从咆哮中挖掘实际问题。
  • 哦,在我使用 GridBagLayout 和 GridBagConstraints 方法之后,如果我最小化然后恢复主窗口,一切看起来都不错。
  • 写完这整篇咆哮的时间足以输入谷歌“Swing 与布局管理器一起工作”,点击官方 Swing 教程的第一击,查看视觉指南​​,确定 BoxLayout 看起来很有希望,并看到一个或多或少做你想要的例子(它包含两个组件,一个是一个)
  • 你的意思是对我研究和尝试过的事情进行了相对彻底的解释的整个3句话?我会马上解决的。
  • Robin:尽管我清楚地提到了我发现并已经尝试过的各种事情,但我想我不得不说:我已经尝试过寻找答案。这就是我在这里发帖的原因。斯奈德,像你们这样的精英 cmets 在致力于帮助程序员找到问题答案的网站上没有业务。由于 Java 的所有内容都已在网上某处记录,因此没有什么是无法通过 Internet 搜索得到的。如果我的问题没有达到你的高标准,那么也许你不应该浪费这么多时间来回答。

标签: java swing layout layout-manager


【解决方案1】:

这样做而不是库和布局:

JLabel jlabel = new JLabel("标签文本", SwingConstants.CENTER);

确保导入 javax.swing.SwingConstants 接口,但不要实现它。它只包含常量,没有方法。

将 JLabel 放在 JPanel 中,否则它将位于 JFrame 或 JWindow(您的顶级容器)的中心。

【讨论】:

    【解决方案2】:

    使用这个。

    labelName.setHorizontalAlignment(SwingConstants.CENTER);
    

    labelName.setHorizontalAlignment(JPanel.CENTER);
    

    它们都必须工作。

    【讨论】:

      【解决方案3】:

      我不喜欢这里的答案。

      在我的职业生涯中,我从未见过有效使用 GridBagLayout。不是说没有,只是说我还没有看到[有效的],并且可能存在相关性。此外,将单个 JLabel 添加到 Container 的中间可能会使其成为演示目的的中心,但是如果您尝试继续使用它而不是其他一些布局,那么以后您将有很多困难.

      我确实喜欢有关 BoxLayout 的建议,因为这实际上是一种很好的方法。也就是说,这个答案只是谜题的一部分,因此我为什么要挖掘一个 7 年前的问题。

      我的“答案”

      您的问题确实没有简短的答案。根据您提出的问题,您的问题有一个确切的答案,但是 StackOverflow 是关于一个社区相互学习的,我怀疑您正在尝试学习如何使用一般布局(或者您是 7 年前)并告诉你输入一个组合键来完成你的演示案例不会教你答案。

      我将尽量不解释任何您无法自行在网络上搜索答案的布局(最后附上 Oracle 教程的链接,因为我认为它很好地解释了不同的布局)。

      框布局

      BoxLayout 是一种实现方式,上面已经有一个代码 sn-p 来演示它,所以我不会提供。如前所述,我将对其进行扩展,仅准确回答您的问题,但并不能真正教给您任何东西。 Glue,正如 BoxLayout 所指的那样,基本上在Container 中的所有“胶水”之间为您提供等量的剩余房地产。所以,如果你要做类似的事情

      panel.add(Box.createHorizontalGlue());
      panel.add(label);
      panel.add(Box.createHorizontalGlue());
      panel.add(otherLabel);
      

      您会发现您的JLabel 不再居中,因为“胶水”只剩下剩余的不动产,两个JLabels 被添加到Container 之后将在两个“槽”之间平均分配(两次调用Container#add(Component) with a glue parameter) in theContainer`。

      边框布局

      BorderLayout 是解决此问题的另一种方法。 BorderLayout 分为 5 个区域。 BorderLayout#CENTER,正如您可能猜到的,是中心区域。关于这个布局以及它如何居中的重要说明是它如何遵循位于中心的Component 的大小。我不会详细说明;我认为,如果您有兴趣,最后的 Oracle 教程已经很好地介绍了它。

      值得注意的

      我想您可以使用GridLayout,但这是一种比GridBagLayout 更简单的方法,我已经说过,即使我认为这不是一个好方法。所以我也不会详述这一点。

      重点

      说了这么多,我认为所有的 LayoutManager 都值得一看。就像与编程有关的任何其他事情一样 - 使用适合工作的工具。不要仅仅因为您以前使用过 X 布局而假设您应该始终使用 X 布局并且没有其他布局是可行的。弄清楚你希望你的显示器是什么样子,以及你认为它在调整组件大小方面应该如何表现,然后选择你认为最适合的。

      选择正确工具的另一个双重含义是,您不必将所有组件放入一个 Container 并让一个布局完成所有工作。没有什么能阻止你(我强烈鼓励你)使用多个 Containers 并将它们组合在一起。使用适合显示部分的布局控制每个Container,并为不同的Container 设置不同的布局。

      重要!!

      这非常重要的原因是因为每个布局都有他们遵守的规则和事物,以及他们尊重的其他事物,然后是其他被有效忽略的事物(例如,首选、最大和最小尺寸)。如果您[正确]使用不同的布局,您会发现您的显示器接受动态调整大小,同时仍然遵循您希望它保持的形状。这是以正确的方式做事和仅仅接受GridBagLayout 之间的一个非常重要的关键区别。

      JPanel outer = new JPanel(new BorderLayout());
      JPanel centerPanel = new JPanel();
      centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.PAGE_AXIS));
      JPanel southPanel = new JPanel(new CardLayout());
      
      outer.add(centerPanel, BorderLayout.CENTER);
      outer.add(southPanel, BorderLayout.SOUTH);
      

      找出适合您的场景的内容,然后继续进行。没有一种万能的方案,除非您想要一些过于繁琐并被其他布局(即 GridBagLayout)变得多余的东西。

      Oracle 教程

      如果您已经做到了这一点,那么我认为您正在寻找尽可能多的信息。在这种情况下,我强烈建议您阅读 Oracle 的布局管理器教程,因为它很好地展示了它们的一般细节:https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html

      【讨论】:

        【解决方案4】:

        假设你的JLabel 被称为label,那么使用:

        label.setHorizontalAlignment(JLabel.CENTER);
        

        【讨论】:

        • 这是错误的。它影响标签内容的位置,而不是标签在容器中的位置。
        【解决方案5】:

        GridBagLayout 设置为JPanel,将不带任何GridBagConstraintsJLabel 设置为JPanelJLabel 将居中

        例子

        import java.awt.*;
        import javax.swing.*;
        
        public class CenteredJLabel {
        
            private JFrame frame = new JFrame("Test");
            private JPanel panel = new JPanel();
            private JLabel label = new JLabel("CenteredJLabel");
        
            public CenteredJLabel() {
                panel.setLayout(new GridBagLayout());
                panel.add(label);
                panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                frame.add(panel);
                frame.setSize(400, 300);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        
            public static void main(String[] args) {
                EventQueue.invokeLater(new Runnable() {
        
                    @Override
                    public void run() {
                        CenteredJLabel centeredJLabel = new CenteredJLabel();
                    }
                });
            }
        }
        

        【讨论】:

        • 感谢 mKorbel,您不仅发布了有用的信息,而且做得如此彻底。不幸的是,这让我陷入了同样的情况,即出现了意外行为(放置 JLabel 后,我的面板中没有出现任何内容)。当我将您的示例填充到我的实际代码中并使用虚拟 JButton 时,JButton 的位置非常完美。我什至在那个 JButton 中添加了一些设置来模仿我的自定义 JLabel,它仍然可以工作,但是当我使用我的 JLabel 时呢?那是事情不起作用的时候。我不明白。一定有什么东西阻止了我的 JLabel 做这些虚拟 JButton 所做的事情。
        【解决方案6】:

        忘记 Java 标准库中的所有 LayoutManager 并使用 MigLayout。根据我的经验,使用通常完全按照您期望的方式工作要容易得多。

        以下是使用 MigLayout 后如何完成任务。

        import javax.swing.JFrame;
        import javax.swing.JLabel;
        import javax.swing.JPanel;
        
        import net.miginfocom.swing.MigLayout;
        
        public class Test
        {
            public static void main( String[] args )
            {
                JFrame frame = new JFrame( );
                JPanel panel = new JPanel( );
        
                // use MigLayout
                panel.setLayout( new MigLayout( ) );
        
                // add the panel to the frame
                frame.add( panel );
        
                // create the label
                JLabel label = new JLabel( "Text" );
        
                // give the label MigLayout constraints
                panel.add( label, "push, align center" );
        
                // show the frame
                frame.setSize( 400, 400 );
                frame.setVisible( true );
            }
        }
        

        其中大部分只是样板文件。关键是布局约束:"push, align center":

        align center 告诉 MigLayout 将 JLabel 放置在其网格单元的中心。

        push 告诉 MigLayout 扩展网格单元以填充可用空间。

        【讨论】:

        • 有一个很棒的 MigLayout 备忘单,地址为:migcalendar.com/miglayout/mavensite/docs/cheatsheet.html
        • 您可以从这里下载最新版本的 MigLayout:migcalendar.com/miglayout/versions/4.0/miglayout-4.0-swing.jar
        • 有趣!感谢您的提示,我将不得不记住这一点,但现在我希望留在 Java 库中。我还是个新手,正在努力学习。
        • 我怀疑大多数人不会想要使用外部库来完成这样的微不足道的事情。使用外部库使您的程序合法化并不可怕,但是当您可以使用 Java 标准库做到这一点时,为什么还要浪费律师的时间呢?而且,使用此 MigLayout 的代码并不比 JavaSE 布局简单。我认为它要复杂得多,因为在添加到 Container 时,组件约束的 LayoutManager 似乎有一个语法相关联。
        【解决方案7】:

        BoxLayout 是要走的路。如果您设置了 X_AXIS BoxLayout,请尝试在组件前后添加水平胶水:

        panel.add(Box.createHorizontalGlue());
        panel.add(label);
        panel.add(Box.createHorizontalGlue());
        

        【讨论】:

          猜你喜欢
          • 2013-04-06
          • 1970-01-01
          • 2013-06-02
          • 1970-01-01
          • 1970-01-01
          • 2018-01-23
          • 1970-01-01
          相关资源
          最近更新 更多