Swing MigLayout 无法增长填充列以填充容器长度 [英] Swing MigLayout cannot grow fill column to fill container length

查看:42
本文介绍了Swing MigLayout 无法增长填充列以填充容器长度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 MigLayout 用于很长的窗口.

我希望推"第二列和第四列以填充整个窗口的所有长度,但我无法实现.列约束中没有push 选项,只有growfill.

这是一个 SCCEE,正如有人曾经建议的,我已经忘记了它的名字:

package com.WindThunderStudio.MigLayoutTest;导入 java.awt.Cursor;导入 java.awt.EventQueue;导入 javax.swing.JFrame;导入 javax.swing.JLabel;导入 javax.swing.JPanel;导入 net.miginfocom.swing.MigLayout;公共类 MigLayoutTest 扩展 JFrame{私有 JFrame 主框架;私人 JPanel 面板;私人 JLabel lblResumenAuto;私人 JLabel lblResumenAutoResult;私人 JLabel lblResumenRazonSocial;私人 JLabel lblResumenRazonSocialResult;私人 JLabel lblResumenPeriodo;私人 JLabel lblResumenPeriodoResult;私人 JLabel lblResumenFechaHora;私人 JLabel lblResumenFechaHoraResult;公共 MigLayoutTest(){跑();}公共无效运行(){mainFrame = new JFrame();mainFrame.setBounds(0, 0, 1250, 500);mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);JPanel p = new JPanel();p.setSize(mainFrame.getSize());p.setLayout(new MigLayout("fill","[max!,grow]","[50:20:30]10[100::]10[20::]10[50!]10[20!]"));mainFrame.setContentPane(p);面板 = 新 JPanel();panel.setLayout(new MigLayout("fillx", "[left, 15%]10[left, grow, 35%]10[left, 15%]10[left, growth, 35%]", "[center]10[中央]"));lblResumenAuto = new JLabel("我的标签 1111111111111");lblResumenAutoResult = new JLabel("11111111111111111111111");panel.add(lblResumenAuto);panel.add(lblResumenAutoResult);lblResumenRazonSocial = new JLabel("我的标签 2222222222");lblResumenRazonSocialResult = new JLabel("2222222222222222222222");panel.add(lblResumenRazonSocial);panel.add(lblResumenRazonSocialResult,"wrap");lblResumenPeriodo = new JLabel("我的标签 33333333333333");lblResumenPeriodoResult = new JLabel("3333333333333333333333333333333333333333333333333333333");panel.add(lblResumenPeriodo);panel.add(lblResumenPeriodoResult);//poner el texto como html puede tener otra linea, porque es muy largolblResumenFechaHora = new JLabel("<html>我的标签<br/> 4444444444444444</html>");lblResumenFechaHoraResult = new JLabel("44444444444444444444444444");panel.add(lblResumenFechaHora);panel.add(lblResumenFechaHoraResult);p.add(panel,"cell 0 0");getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));setBounds(0, 0, 1250, 500);getContentPane().add(mainFrame.getContentPane());盒();设置可见(真);setLocationRelativeTo(null);设置可调整大小(真);}公共静态无效主(字符串 [] args){EventQueue.invokeLater(new Runnable() {@覆盖公共无效运行(){MigLayoutTest 测试 = new MigLayoutTest();}});}}

如果您运行代码,您会注意到列的宽度随着其包含文本的长度变化而增加.但它永远不会填满其容器的整个宽度.

理想的是,将第 0 列和第 2 列固定为整个宽度的 15%,并让 13 列占据其余部分,35%,前两列占据整个宽度的 50% 大小.

我在这里遗漏了什么吗?我不想指定每列的宽度,设置 pre:min:max,因为这是不好的做法,正如

我的屏幕大小是 1280 x 1024,程序窗口的大小是 914 x 301.

我建议使用以下方法之一:

要将其设置为 1250 x 500 像素的恒定大小,请在 packsetVisible 之间移动 setSize:

<代码>...盒();setSize(1250, 500);

我会使用 setSizesetBounds 没有意义,因为通过调用 setLocationRelativeTo(null) 你将程序的窗口居中屏幕无论如何,所以原点被立即解除.

pack之前设置主窗口的首选大小,以水平最大化并让高度为500像素:

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();setPreferredSize(new Dimension(screenSize.width, 500));

并在水平方向上最大化并让首选高度保持原样:

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();setPreferredSize(new Dimension(screenSize.width, getPreferredSize().height));

当然,您也可以通过设置首选大小而不是使用 setSize 来使窗口变大 1250 x 500.

调整大小的问题现在不是那么大,但它仍然存在 - 使窗口更宽,而不是将其缩小一点.您会注意到即使窗口变窄,panel 也会变宽.问题是 panel 组件最初没有足够大来填充 p 的一列(顺便说一句,您可以向每个 MigLayout 添加调试"标志,也可以面板 - 然后它也会勾勒出所有内部组件).

为了让它填满父容器,像这样添加:

p.add(panel, "cell 0 0,grow");

现在它从一开始就是 p 的全宽,并且按预期调整大小.

关于使用 invokeLater 启动 JFrame - 我们通常在没有它的情况下启动我们的主窗口,并且从来没有出现过问题,因为在第一帧出现之前没有与 Swing 的交互可见,但我刚刚注意到它被认为是最佳实践 - 即使在 Oracle 的教程中也是如此.看来我也在这里学到了一些东西:-).

添加和不添加grow"的框架窗口对比

测试场景:启动应用程序并将其调整为更宽.

正如您在第一个屏幕截图中看到的,组件大小小于列宽 - 看起来组件在调整大小时位于列大小之后.在第二个屏幕截图中,组件宽度始终与列宽相同.正如我之前所说,原因可能是 Java 和/或操作系统的组合,我不知道.但显然它的行为有所不同,并且在我的机器上不是最佳的.

I am using MigLayout for a very long window.

and I wish to "push" the second and fourth column to fill all the length of the whole window, but I cannot achieve it. There's no push option in column constraint, only grow and fill.

Here's a SCCEE, as someone once suggested, whose name I already forgot:

package com.WindThunderStudio.MigLayoutTest;

import java.awt.Cursor;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import net.miginfocom.swing.MigLayout;

public class MigLayoutTest extends JFrame{
private JFrame mainFrame;
private JPanel panel;

private JLabel lblResumenAuto;
private JLabel lblResumenAutoResult;
private JLabel lblResumenRazonSocial;
private JLabel lblResumenRazonSocialResult;
private JLabel lblResumenPeriodo;
private JLabel lblResumenPeriodoResult;
private JLabel lblResumenFechaHora;
private JLabel lblResumenFechaHoraResult;

public MigLayoutTest(){
    run();
}

public void run(){
    mainFrame = new JFrame();
    mainFrame.setBounds(0, 0, 1250, 500);
    mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    JPanel p = new JPanel();
    p.setSize(mainFrame.getSize());

    p.setLayout(new MigLayout("fill","[max!, grow]","[50:20:30]10[100::]10[20::]10[50!]10[20!]"));
    mainFrame.setContentPane(p);

    panel = new JPanel();
    panel.setLayout(new MigLayout("fillx", "[left, 15%]10[left, grow, 35%]10[left, 15%]10[left, grow, 35%]", "[center]10[center]"));

    lblResumenAuto = new JLabel("MY LABEL 1111111111111");
    lblResumenAutoResult = new JLabel("1111111111111111111111");

    panel.add(lblResumenAuto);
    panel.add(lblResumenAutoResult);

    lblResumenRazonSocial = new JLabel("MY LABEL 2222222222");
    lblResumenRazonSocialResult = new JLabel("2222222222222222222222");

    panel.add(lblResumenRazonSocial);
    panel.add(lblResumenRazonSocialResult,"wrap");

    lblResumenPeriodo = new JLabel("MY LABEL 33333333333333");
    lblResumenPeriodoResult = new JLabel("3333333333333333333333333333333333333333333333333333333");

    panel.add(lblResumenPeriodo);
    panel.add(lblResumenPeriodoResult);
    //poner el texto como html puede tener otra linea, porque es muy largo
    lblResumenFechaHora = new JLabel("<html>MY LABEL <br /> 4444444444444444</html>");
    lblResumenFechaHoraResult = new JLabel("4444444444444444444444444");

    panel.add(lblResumenFechaHora);
    panel.add(lblResumenFechaHoraResult);

    p.add(panel,"cell 0 0");

    getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    setBounds(0, 0, 1250, 500);
    getContentPane().add(mainFrame.getContentPane());

    pack();
    setVisible(true);
    setLocationRelativeTo(null);
    setResizable(true);
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {

        @Override
        public void run() {
            MigLayoutTest test = new MigLayoutTest();

        }
    });
}
}

If you run the code, you can note that the columns' width increases as its containing text's length changes. But it never fills the whole width of its container.

What's desirable, is to fix the column 0 and 2 by 15% of the whole width, and let column 1 and 3 to ocupy the rest, 35%, with the first two columns occupying the 50% size of the whole width.

Am I missing something here? I don't want to specify the width of every column, setting pre:min:max, because it is bad practice, as suggested by this post, which gets lots of vote up.

panel.setLayout(new MigLayout("fillx", 
                              "[left, 15%]10[left, grow, 35%]10[left, 15%]10[left, grow, 35%]", 
                              "[center]10[center]"));

But, if I set pref:min:max, it can fill the whole width.

解决方案

First the code, then explanation. Try this:

import java.awt.Cursor;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import net.miginfocom.swing.MigLayout;

public class MigLayoutTest extends JFrame {
  private JPanel panel;

  private JLabel lblResumenAuto;
  private JLabel lblResumenAutoResult;
  private JLabel lblResumenRazonSocial;
  private JLabel lblResumenRazonSocialResult;
  private JLabel lblResumenPeriodo;
  private JLabel lblResumenPeriodoResult;
  private JLabel lblResumenFechaHora;
  private JLabel lblResumenFechaHoraResult;

  public MigLayoutTest() {
    run();
  }

  public void run() {
    panel = new JPanel();
    panel.setLayout(new MigLayout("debug, fill",
        "[left, 15%]10[left, 35%]10[left, 15%]10[left, 35%]", "[center]10[center]"));

    lblResumenAuto = new JLabel("MY LABEL 1111111111111");
    lblResumenAutoResult = new JLabel("1111111111111111111111");

    panel.add(lblResumenAuto, "sg label");
    panel.add(lblResumenAutoResult, "sg value");

    lblResumenRazonSocial = new JLabel("MY LABEL 2222222222");
    lblResumenRazonSocialResult = new JLabel("2222222222222222222222");

    panel.add(lblResumenRazonSocial, "sg label");
    panel.add(lblResumenRazonSocialResult, "sg value, wrap");

    lblResumenPeriodo = new JLabel("MY LABEL 33333333333333");
    lblResumenPeriodoResult = new JLabel("3333333333333333333333333333333333333333333333333333333");

    panel.add(lblResumenPeriodo, "sg label");
    panel.add(lblResumenPeriodoResult, "sg value");
    // poner el texto como html puede tener otra linea, porque es muy largo
    lblResumenFechaHora = new JLabel("<html>MY LABEL <br /> 4444444444444444</html>");
    lblResumenFechaHoraResult = new JLabel("4444444444444444444444444");

    panel.add(lblResumenFechaHora, "sg label");
    panel.add(lblResumenFechaHoraResult, "sg value");

    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    getContentPane().add(panel);

    pack();
    setVisible(true);
    setLocationRelativeTo(null);
    setResizable(true);
  }

  public static void main(String[] args) {
    MigLayoutTest test = new MigLayoutTest();
  }

}

The explanation of my changes:

Now except for simplifying the code and layout I used "debug" within the layout constraints to see what actually happens to the layout. I suggest using it anytime things go wrong with the layout - it makes MigLayout draw the borders of components and cells, thus visualizing potential problems.

I removed the unnecessary mainframe and p - if you really need it for a nested layout try to add it once you have solved the inner layout to your liking.

As to p and panel - it might be that you need here two different layouts, one nested in another, but this is the actual source of your problem. p had also its own grid layout, with

p.add(panel,"cell 0 0");

you put panel in the top left cell of the p - this is why panel was not distributed over the whole window but sat in the upper left corner.

As you see without p it positions nicely in the middle of the screen without any constant size, still showing all components, but more importantly it has 50% of the window size for the first and 50% for the last two columns. This was achieved by giving the components a "sizegroup":

Gives the component a size group name. All components that share a size group name will get the same BoundSize (min/preferred/max). It is used to make sure that all components in the same size group gets the same min/preferred/max size which is that of the largest component in the group. An empty name "" can be used.

And it also resizes like it should!

The nested layout might also had been the root of another problem – don’t know if you didn’t notice it or it just didn’t show up on your machine, but if I tried to resize your window the panel got wider and wider (never narrower) even if I shrunk the window. At some point it got wider than the window itself and even then growed further on each resize.

Next - setting the dimensions to a constant value didn’t make sense, since after pack the layout manager starts sizing everything based on preferred sizes of the window and its content. Besides, you never know which size is your users’ screen, so any constant size could be equally bad if effectively used. Better to drive the size through the content and available runtime environment. With your code on my machine it took all available horizontal space of my two screens (2 x 1280) and did’t look pretty.

I also think that you do not need to start the frame using EventQueue.invokeLater, just create a MigLayoutTest and that’s it.

EDIT after OP's own answer

Setting the size using setBounds(0, 0, 1250, 500) before pack is not working correctly (by this I mean making the window be that size). Even in the screenshot below OP's own answer it is not 500px high. Here is what I get on Windows 7 running JDK 1.8.0_91:

The size of my screen is 1280 x 1024, the size of the programm's window is 914 x 301.

I'd suggest using one of the following:

To set it to the constant size of 1250 x 500 px move the setSize between pack and setVisible:

...
pack();
setSize(1250, 500);

I'd use setSize, setBounds doesn't make sense, since by calling setLocationRelativeTo(null) you centering the programm's window on the screen anyway, so the origin is being dismissed immediately.

To maximize horizontally and let the height be 500 px set main window's preferred size before pack:

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(new Dimension(screenSize.width, 500));

And to maximize horizontally and let the preferred height as it was originally:

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(new Dimension(screenSize.width, getPreferredSize().height));

Of course you can make the window 1250 x 500 big by setting its preferred size instead of using setSize, too.

The resize problem is not so big now, but it's still there - make the window wider, than narrow it just a little bit. You'll notice that the panel gets wider even if the window got narrowed. The problem is that panel component doesn't get big enough to fill the one column of p initially (BTW you can add the 'debug' flag to each MigLayout, also that of the panel - it will then outline all of the inner components as well).

To make it fill the parent container add it like this:

p.add(panel, "cell 0 0, grow");

Now it is the full width of p from the very beginning and resizing works as expected.

Regarding starting the JFrame using invokeLater - we start our main windows usually without it and had never had problems, since there were no interactions with Swing until the first frame was visible, yet I have just noticed that it is regarded to be the best practise - even in Oracle's tutorials. It looks like I had learned something here, too :-).

Comparision of the frame's window with and without adding with "grow"

Test scenario: start the application and resize it to be wider.

As you see in the first screenshot the component size is smaller than the column width - it looks like the component were lying behind the column size while resizing. On the second screenshot the component width remains the same as the column width at all times. As I said previously the reason might be the Java and/or operating system combination, I don't know. But obviously it behaves differently and on my machine less than optimal.

这篇关于Swing MigLayout 无法增长填充列以填充容器长度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆