GridBagLayout 的固定宽度

发布于 2024-11-26 16:46:27 字数 2836 浏览 1 评论 0原文

在此处输入图像描述

我正在使用 GridBagLayout 制作一个 StatusBar,如图所示。我有 4 个区域,所以我在第一个区域有一个按钮,然后在第二个区域有信息消息,然后我想要另外两个区域(我还有第五个区域来形成角落)。

按钮区域完美契合,因为内容始终是具有相同宽度的按钮。与角落区域相同。信息区域必须获得所有可用空间。第三和第四区域必须具有固定值,与屏幕尺寸无关。

我怎样才能做到这一点?

我当前的代码是:

public MyStatusBar() {
        setLayout(new GridBagLayout());
        setPreferredSize(new Dimension(getWidth(), 23));
        GridBagConstraints c = new GridBagConstraints();

        botonDispositivo = new JButton("");
        this.setText(0, "Disconnected");
        URL imageUrl = getClass().getResource("resources/22x22/dispositivo01.png");
        this.setButtonImg(imageUrl);
        this.setButtonEnabled(false);


        c.gridx = 0;
        c.gridy = 0;
        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.WEST;
        c.gridwidth = 1;
        c.gridheight = 1;
        this.add(botonDispositivo, c);

        c.insets= new Insets(0,10,0,0);
        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.7;
        c.fill = GridBagConstraints.HORIZONTAL;
        msgLabel = new JLabel("");
        msgLabel.setPreferredSize(new Dimension(500, msgLabel.getHeight()));
        this.add(msgLabel, c);
        this.setText(1, "Waiting for potentiostat conection");

        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.0;
        c.fill = GridBagConstraints.NONE;
        this.add(new SeparatorPanel(Color.GRAY, Color.WHITE), c);

        c.gridx ++;
        c.gridy = 0;
        c.fill = GridBagConstraints.NONE;
        c.weightx = 0.0;
        overErrorLabel = new JLabel("");
        overErrorLabel.setSize(new Dimension(150, overErrorLabel.getHeight()));
        this.add(overErrorLabel, c);
        //this.setText(2, "");

        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.0;
        c.fill = GridBagConstraints.NONE;
        this.add(new SeparatorPanel(Color.GRAY, Color.WHITE), c);

        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.0;
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.EAST;
        timeLabel = new JLabel("");
        timeLabel.setMinimumSize(new Dimension(150, timeLabel.getHeight()));
        //timeLabel.setMaximumSize(new Dimension(150, timeLabel.getHeight()));
        this.add(timeLabel, c);
        //this.setText(3, "");


        JPanel rightPanel = new JPanel(new GridBagLayout());
        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.0;
        c.fill = GridBagConstraints.BOTH;
        rightPanel.add(new JLabel(new AngledLinesWindowsCornerIcon()), c);
        rightPanel.setOpaque(false);

        c.gridx ++;
        c.gridy = 0;
        c.fill = GridBagConstraints.BOTH;
        this.add(rightPanel, c);

        setBackground(SystemColor.control);
      }

enter image description here

I'm using GridBagLayout to make a StatusBar which looks like in the picture. I have 4 areas, so I have a button in the first one, then info messages in the second one, and then I want two more (and i also have a fifth one to make the corner).

The button area fits perfectly, because the content is always a button with the same width. Same with the corner area. The info area must get all the space available. 3rd and 4th areas must have a fixed value, independent from the screen size.

How can I do that?

My current code is:

public MyStatusBar() {
        setLayout(new GridBagLayout());
        setPreferredSize(new Dimension(getWidth(), 23));
        GridBagConstraints c = new GridBagConstraints();

        botonDispositivo = new JButton("");
        this.setText(0, "Disconnected");
        URL imageUrl = getClass().getResource("resources/22x22/dispositivo01.png");
        this.setButtonImg(imageUrl);
        this.setButtonEnabled(false);


        c.gridx = 0;
        c.gridy = 0;
        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.WEST;
        c.gridwidth = 1;
        c.gridheight = 1;
        this.add(botonDispositivo, c);

        c.insets= new Insets(0,10,0,0);
        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.7;
        c.fill = GridBagConstraints.HORIZONTAL;
        msgLabel = new JLabel("");
        msgLabel.setPreferredSize(new Dimension(500, msgLabel.getHeight()));
        this.add(msgLabel, c);
        this.setText(1, "Waiting for potentiostat conection");

        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.0;
        c.fill = GridBagConstraints.NONE;
        this.add(new SeparatorPanel(Color.GRAY, Color.WHITE), c);

        c.gridx ++;
        c.gridy = 0;
        c.fill = GridBagConstraints.NONE;
        c.weightx = 0.0;
        overErrorLabel = new JLabel("");
        overErrorLabel.setSize(new Dimension(150, overErrorLabel.getHeight()));
        this.add(overErrorLabel, c);
        //this.setText(2, "");

        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.0;
        c.fill = GridBagConstraints.NONE;
        this.add(new SeparatorPanel(Color.GRAY, Color.WHITE), c);

        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.0;
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.EAST;
        timeLabel = new JLabel("");
        timeLabel.setMinimumSize(new Dimension(150, timeLabel.getHeight()));
        //timeLabel.setMaximumSize(new Dimension(150, timeLabel.getHeight()));
        this.add(timeLabel, c);
        //this.setText(3, "");


        JPanel rightPanel = new JPanel(new GridBagLayout());
        c.gridx ++;
        c.gridy = 0;
        c.weightx = 0.0;
        c.fill = GridBagConstraints.BOTH;
        rightPanel.add(new JLabel(new AngledLinesWindowsCornerIcon()), c);
        rightPanel.setOpaque(false);

        c.gridx ++;
        c.gridy = 0;
        c.fill = GridBagConstraints.BOTH;
        this.add(rightPanel, c);

        setBackground(SystemColor.control);
      }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南城追梦 2024-12-03 16:46:27

您可以为不同的标签设置首选、最小、最大等尺寸。
我认为您需要的只是设置权重 X>0 并为您想要调整大小的标签填充 param=HORIZONTAL 约束,为您不想调整大小的标签设置weightX=0 并填充 NONE 。

还可以使用 ipadx 指定标签的最小尺寸。

You set preferred, minimum, maximul etc. size for different labels.
I think all you need is set weight X>0 and fill param=HORIZONTAL of the constraint for the label you want to be resized and weightX=0 and fill-NONE for the labels you don't want to be resized.

Also use ipadx to specify min size for labels.

烈酒灼喉 2024-12-03 16:46:27

为了更好、最简单地向 GUI 输出,最好使用 Borderlayout

JPanel#setPrefferedSize(200, 30); for JButtonIcon 和 JLabel 放置到 WEST 区域

JPanel#setPrefferedSize(200, 30); (rightPanel) 到EAST 区域

将另一个 JPanel 放置到 CENTER 区域

for better and easiest output to the GUI is better look for Borderlayout,

JPanel#setPrefferedSize(200, 30); for JButton with Icon and JLabel put to the WEST area

JPanel#setPrefferedSize(200, 30); (rightPanel) to the EAST area

put another JPanel to CENTER area

痴者 2024-12-03 16:46:27

如果您希望 GridBagLayout 内的单元格的宽度(或高度)固定,那么有一个可行的解决方案。假设您希望 (x,y) 处的单元格宽度固定,但其中的 JLabel 具有可变内容,必须在运行时更改。如果 JLabel 需要更改大小,则使用 GridBagLayout 将重新定位其他组件,从而强制调整包含单元格的大小。为了解决这个问题,您可以执行以下操作之一:

  • 您可以向布局中添加一个额外的行 (y + 1),其中第 x 个单元格包含一个虚拟 JPanel,并在该 JPanel 上调用 .setPreferredSize(new Dimension(所需宽度,0));
  • 相同,但不是设置 PreferredSize,而是在添加此虚拟面板时使用的 GridBagConstraints 对象上设置插图。因此,如果您想要固定宽度,只需执行 gbc.insets = new Insets(0,preferredWidth,0,0);gbc.insets = new Insets(0,0,0,优选宽度);。这样,面板本身的尺寸为 (0,0),但包含的单元格将被迫达到您指定的宽度(因为从组件来看,插图是外部填充)。

第一个要求你调用 setPreferredSize() ,这总是让我感到不舒服,因为你扰乱了 LayoutManager 的任务。因此,我更喜欢后一种解决方案,但您将无法可视化您的单元,因为您的虚拟面板没有尺寸。在前一个解决方案中,您可以通过为面板指定背景颜色来使单元格可见。

这种方法的好处是,您不必费心设置 JLabel 的尺寸,尤其是其高度,在显示之前是未知的。您无法在 JLabel 上设置 PreferredSize,因为您不知道它必须具有哪个高度(取决于平台、取决于字体等)。您只需添加它,然后将虚拟行与虚拟面板一起使用将强制包含 JLabel 的单元格与 desiredWidth 一样宽。

该解决方案的工作原理是 JLabel 的宽度不会超过desiredWidth,因为在这种情况下单元格也会增长。您始终可以在 JLabel 上设置 maxSize 来解决此问题(这里您不会遇到未知高度的问题 - 对于最大高度,您可以使用 Integer.MAX_VALUE)。

对于高度也是如此,只需引入一个虚拟列,并在出现问题的行的单元格中添加一个维度 = (0, PreferredHeight) 的虚拟 JPanel 即可。

这种方法的缺点是:您必须使用虚拟组件,这从来都不是最好的方法,但它在这里效果很好。

If you want a cell inside a GridBagLayout to be fixed in width (or height), then there is a working solution for this. Say you want cell at (x,y) to be fixed in width but the JLabel inside it has variable content, that must be changed during runtime. Using a GridBagLayout would then relocate other components if the JLabel needs to change size, thus forcing the containing cell to be resized. To counter this you can do one of the following:

  • You can add an extra row (y + 1) to the layout in which the xth cell contains a dummy JPanel, and on that JPanel you call .setPreferredSize(new Dimension(desiredWidth, 0));.
  • The same, but instead of setting the preferredSize you set the insets on the GridBagConstraints object used while adding this dummy panel. So if you want a fixed width, just do gbc.insets = new Insets(0,preferredWidth,0,0); or gbc.insets = new Insets(0,0,0,preferredWidth);. This way the panel itself is (0,0) in dimension but the containing cell will be forced to be as wide as you specify (because the insets are the external padding, seen from the component).

The first one requires you to call setPreferredSize() and this always makes me feel uncomfortable, because you are messing with the task of the LayoutManager. Therefore I prefer the latter solution but you will not be able to visualize your cell as your dummy panel has no size. In the former solution you can make your cell visible by giving the panel a background color.

The benefits of this approach is that you don't have to bother about setting sizes on your JLabel, especially its height which is unknown before it is displayed. You can't set a preferredSize on the JLabel because you don't know which height it must have (platform dependent, font dependent etc.). You just add it, and using the dummy row with the dummy panel will force the cell containing the JLabel to be as wide as desiredWidth.

This solution works given that the JLabel's width will not exceed desiredWidth, because in that case the cell will also grow. You can always put a maximumSize on the JLabel to solve this (here you don't have the problem of unknown heights - for maximum height you can use Integer.MAX_VALUE).

The same story goes for height, just introduce a dummy column and add a dummy JPanel with dimension = (0, preferredHeight) in the cell at the row where the problem occurs.

Downside of this approach: you have to use dummy components which is never the best way to go, but it works quite well here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文