调整 FlowLayout 面板的大小

4
我想创建一个使用FlowLayout的JPanel。这个面板放置在一个使用BorderLayout的容器中。然后,将该容器添加到一个使用CardLayout的卡片中。我希望使用FlowLayout的面板成为BorderLayout面板左下角的一个小方框。我应该如何做?我已经使用了"settingsPanel.setPreferredSize(new Dimension(10, 425));",但无论我设置什么大小,宽度仍跨越整个面板,尽管高度发生了改变。我应该如何改变宽度?
代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class Main {
    //Settings Panel variables
    JLabel settingsTitle = new JLabel("Settings");

    public Main()
    {
        JPanel mainCard = new JPanel(new BorderLayout(8,8));
        JPanel settingsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        settingsTitle.setFont(new Font("TimesRoman", Font.PLAIN, 35));
        settingsPanel.add(settingsTitle);

        final CardLayout layout = new CardLayout();
        final JPanel cards = new JPanel(layout);
        cards.add(mainCard, "2");

        mainCard.add(settingsPanel, BorderLayout.SOUTH);

        settingsPanel.setPreferredSize(new Dimension(10, 425));
        settingsPanel.setBorder(BorderFactory.createLineBorder(Color.black));

        layout.show(cards, "1");

        JFrame window = new JFrame("Test");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.getContentPane().add(cards);
        window.setSize(1280, 720);
        window.setLocationRelativeTo(null);
        window.setResizable(false);
        window.setVisible(true);

    }

    public static void main(String[] args)
    {

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main();
            }
        });

    }
}

示例:

输入图像描述

这是一个关于IT技术的示例,展示了一张图片。

1
+1 for Minimal, Complete, Tested and Readable example。这样做可以使测试更容易,答案也更快得到。 - dic19
谢谢,我这次确保格式正确了。上次很抱歉。 - user3255328
2个回答

2
所以,以下是使用GridBagLayout更改BorderLayout的代码。 GridBagLayout的核心思想是您将具有多个行和列(不同大小)的网格,并且可以在每个单元格中放置组件。它的好处是非常强大的:当您将组件放在单元格中时,可以自定义以下内容:
  • 它可以跨越多少个单元格(垂直,水平或两者)(gridwidth / gridheight)
  • 在单元格中放置在哪里:中心,左上角,右下角...(anchor)
  • 每行/列的权重,这是它们在调整大小/分配窗口时所占用的空间比例。(weightx,weighty)
  • 它们是否必须占用最大或最小的必要空间。(fill)

除其他事项外。最后一点是您在这里遇到的问题,BorderLayout强制使面板尽可能扩展。在我的代码中,我使用了fill = NONE并将其设置为anchor = LAST_LINE_START,因此它停留在左下角而不会扩展。

您可以玩弄这些参数,所有信息都在教程中。其中关键是要知道您的网格如何。在此示例中,它非常简单,只是1x1。但是看看教程:那些带有红色网格的图像,这就是您必须在脑海中拥有的内容。除此之外,了解所有变量之外,唯一棘手的事情就是权重如何工作。

    import java.awt.BorderLayout;
    import java.awt.CardLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;

    import javax.swing.BorderFactory;
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;    
    public class Main {
    //Settings Panel variables
    JLabel settingsTitle = new JLabel("Settings");

    public Main()
    {
        JPanel mainCard = new JPanel(new GridBagLayout());
        JPanel settingsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        settingsTitle.setFont(new Font("TimesRoman", Font.PLAIN, 35));
        settingsPanel.add(settingsTitle);

        final CardLayout layout = new CardLayout();
        final JPanel cards = new JPanel(layout);
        cards.add(mainCard, "2");

        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 0;
        c.weightx = 1.0;
        c.weighty = 1.0;
        c.anchor = GridBagConstraints.LAST_LINE_START;
        c.fill = GridBagConstraints.NONE; //uneeded line because it's the default value, but it has to be NONE

        mainCard.add(settingsPanel, c);

       // settingsPanel.setPreferredSize(new Dimension(300, 425)); //the components inside settingsPanel will set its side
        settingsPanel.setBorder(BorderFactory.createLineBorder(Color.black));

        layout.show(cards, "1");

        JFrame window = new JFrame("Test");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.getContentPane().add(cards);
        window.setSize(1280, 720); ///replace with window.pack()
        window.setLocationRelativeTo(null);
        window.setResizable(false);
        window.setVisible(true);

    }

    public static void main(String[] args)
    {

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main();
            }
        });

    }
}

我应该避免在Java Swing中使用set(Preferred|Maximum|Minimum)Size方法吗?是的,你应该避免使用。组件的定位和大小是布局管理器的任务。请参见链接。答案是由一个真正的Swing专家编写的。 - dic19
@dic19 当然,他忘记删除它,因为它在他的原始代码中。设置面板内部的组件将适当地定义其大小。您可以使用它暂时查看它的外观。 - DSquare
+1 for the edit. 仍需将 window.setSize(1280, 720) 替换为 window.pack()。顺便提一下:JFrame 的内容面板默认布局管理器是 BorderLayout。因此,这行代码:window.getContentPane().add(cards); 实际上是将 cards 面板添加到一个使用 BorderLayout 的容器中 ;) - dic19
我终于有机会看一下这个了,除了 GridBagConstraints c = new GridBagConstraints 以外,我都理解了。我需要将 c 应用到每个面板上吗?它是做什么的,如何工作等等。 - user3255328
1
@HarryKitchener 当你使用没有约束条件的add(component)方法时,你只是告诉容器使用默认的约束条件。例如,对于BorderLayout来说,它的默认值是“CENTER”。或者GridLayout不需要约束条件,因为它已经知道在构造函数中定义的网格中放置组件的位置。但是对于GridBagLayout来说情况并非如此,你总是需要放置约束条件,注意到我所有的添加操作都将c作为第二个参数传递给了container.add(component, c) - DSquare
显示剩余3条评论

1
首先要摆脱这个: settingsPanel.setPreferredSize(new Dimension(10, 425)),让布局管理器来完成它们的工作。
我能想到的最简单的方法就是在一个不同的面板中包装settingsPanel,并将这个面板添加到SOUTH。
 JPanel wrapPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
 wrapPanel.add(settingsPanel);

 JPanel mainCard = new JPanel(new BorderLayout(8,8));
 mainCard.add(wrapPanel, BorderLayout.SOUTH); // add wrapPanel here instead of settingsPanel

这样您就可以利用FlowLayout属性来填充它所需的较小空间:

enter image description here

虽然离题了,但我认为它很值得

正如我已经在你的上一个问题中评论的那样,这个面板的东西让我想起了这个Portal 2:面板视频。我们也需要一些时间来笑笑,你不觉得吗?


1
这是正确的,但只是解决实际问题的一种方法:边框布局(BorderLayout),我建议将其更改为GridBagLayout,特别是如果您需要放置更多具有非平凡位置的组件,如此之类。 - DSquare
1
同意@DSquare的观点。您的UI(至少我们可以看到的部分)没有以“边框”样式布局。因此,避免使用BorderLayout。Swing中的大多数布局管理器都旨在解决特定的常见UI布局问题(例如,FlowLayout用于按钮栏,BorderLayout用于具有主内容区域的UI等)。GridBagLayout是通用的、最灵活的布局管理器,可解决不适合其他布局的要求。 - matt forsythe
谢谢你的建议。我之前看过GridBagLayout,但是真的很困惑。能否解释一下? - user3255328
1
@HarryKitchener 我马上会发布一个使用GridBagLayout的答案。 - DSquare
如果我没记错的话,OP正在尝试在底部使用一些按钮和一个主要内容放置在中心的向导。请查看他的之前的问题。所以,是的,这是一种“边框”样式。 - dic19
显示剩余2条评论

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