Swing MigLayout 无法增长填充列以填充容器长度
Swing MigLayout cannot grow fill column to fill container length
我使用 MigLayout
的时间很长 window。
我希望"push"第二列和第四列填满整个window的所有长度,但我无法实现。列约束中没有 push
选项,只有 grow
和 fill
。
这里有一个 SCCEE,正如有人曾经建议的那样,我已经忘记了他的名字:
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();
}
});
}
}
如果您 运行 代码,您会注意到列的宽度随着其包含文本长度的变化而增加。但它永远不会填满其容器的整个宽度。
可取的是,将第0列和第2列固定15%
整个宽度,让1
和3
列占据其余部分,35%
, 前两列占整个宽度的50%。
我是不是漏掉了什么?我不想指定每一列的宽度,设置 pre:min:max
,因为这是不好的做法,正如 this post 所建议的那样,它获得了很多投票。
panel.setLayout(new MigLayout("fillx",
"[left, 15%]10[left, grow, 35%]10[left, 15%]10[left, grow, 35%]",
"[center]10[center]"));
但是,如果我设置pref:min:max
,它可以填满整个宽度。
先是代码,再是解释。试试这个:
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();
}
}
我的改动说明:
现在除了简化代码和布局外,我在布局约束内使用“调试”来查看布局实际发生了什么。我建议在布局出现问题时使用它 - 它使 MigLayout
绘制组件和单元格的边界,从而可视化潜在的问题。
我删除了不必要的 mainframe
和 p
- 如果您真的需要它用于嵌套布局,请在您根据自己的喜好解决内部布局后尝试添加它。
至于 p
和 panel
- 您可能需要两种不同的布局,一个嵌套在另一个布局中,但这是问题的实际根源。 p
也有自己的网格布局,
p.add(panel,"cell 0 0");
你把 panel
放在 p
的左上角单元格中 - 这就是为什么 panel
没有分布在整个 window 而是坐在左上角的原因角落.
如您所见,没有 p
它很好地位于屏幕中间,没有任何恒定大小,仍然显示所有组件,但更重要的是它有 50% 的 window 大小用于第一列和最后两列的 50%。这是通过给组件一个“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.
而且它还可以按应有的方式调整大小!
嵌套布局也可能是另一个问题的根源——不知道你是否注意到它或者它只是没有出现在你的机器上,但如果我试图调整你的 window 即使我缩小 window,panel
变得越来越宽(从不变窄)。在某些时候,它变得比 window 本身更宽,甚至在每次调整大小时都进一步增长。
接下来 - 将尺寸设置为常量值没有意义,因为在 pack
之后布局管理器开始根据 window 及其内容的首选大小调整所有内容的大小。此外,您永远不知道用户的屏幕尺寸是多少,因此如果有效使用,任何固定尺寸都可能同样糟糕。最好通过内容和可用的运行时环境来驱动大小。在我的机器上使用你的代码,它占用了我两个屏幕 (2 x 1280) 的所有可用水平 space,并且看起来不漂亮。
我也认为你不需要使用EventQueue.invokeLater
开始框架,只需创建一个MigLayoutTest
就可以了。
在 OP 自己的回答后进行编辑
在 pack
之前使用 setBounds(0, 0, 1250, 500)
设置大小无法正常工作(我的意思是让 window 成为那个大小)。即使在 OP 自己的答案下方的屏幕截图中,它也不是 500px 高。这是我在 Windows 7 运行 JDK 1.8.0_91:
上得到的
我的屏幕尺寸是 1280 x 1024,程序的尺寸 window 是 914 x 301。
我建议使用以下其中一项:
要将其设置为 1250 x 500 像素的恒定大小,请将 setSize
移动到 pack
和 setVisible
之间:
...
pack();
setSize(1250, 500);
我会使用 setSize
,setBounds
没有任何意义,因为通过调用 setLocationRelativeTo(null)
你无论如何都会在屏幕上居中程序的 window,所以origin 被立即解雇。
要水平最大化并让高度为 500 像素,请在 pack
之前设置主要 window 的首选大小:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(new Dimension(screenSize.width, 500));
并水平最大化并让首选高度保持原样:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(new Dimension(screenSize.width, getPreferredSize().height));
当然,您也可以通过设置其首选大小而不是使用 setSize
来使 window 1250 x 500 变大。
调整大小的问题现在不是那么大,但它仍然存在 - 让 window 变宽,而不是缩小它一点点。您会注意到 panel
变宽了,即使 window 变窄了。问题是 panel
组件最初不够大,无法填充 p
的一列(顺便说一句,您可以将 'debug' 标志添加到每个 MigLayout,也是 panel
- 然后它也会概述所有内部组件)。
要使其填充父容器,请像这样添加它:
p.add(panel, "cell 0 0, grow");
现在它从一开始就是 p
的全宽,并且按预期调整大小。
关于使用 invokeLater
启动 JFrame
- 我们启动我们的主要 windows 通常没有它并且从未遇到过问题,因为在第一帧之前没有与 Swing 交互可见,但我刚刚注意到它被认为是最佳实践 - 即使在 Oracle 的教程中也是如此。看来我在这里也学到了一些东西:-)。
帧的window添加和不添加"grow"
的比较
测试场景:启动应用程序并将其调整为更宽。
正如您在第一个屏幕截图中看到的那样,组件尺寸小于列宽 - 看起来组件在调整大小时位于列尺寸后面。在第二个屏幕截图中,组件宽度始终与列宽保持相同。正如我之前所说,原因可能是 Java and/or 操作系统组合,我不知道。但显然它的行为有所不同,并且在我的机器上表现不佳。
感谢@Tomasz Stanczak,我终于解决了。但是,我发现他说的部分是相关的,而其他部分则不是。对于以后可能看到的读者,我必须说得更清楚一些。
最终的工作代码是:
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 MigLayoutMySCCEE 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 MigLayoutMySCCEE(){
run();
}
public void run(){
JPanel p = new JPanel();
p.setLayout(new MigLayout("debug, fill","[grow]","[50:20:30]10[100::]10[20::]10[50!]10[20!]"));
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");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
setBounds(0, 0, 1250, 500);
getContentPane().add(p);
pack();
setVisible(true);
setLocationRelativeTo(null);
setResizable(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MigLayoutMySCCEE test = new MigLayoutMySCCEE();
}
});
}
}
而 window 看起来像:
一些注意事项:
debug
技巧非常有用,促使我再次阅读 DOC。不过,我希望它能在“快速启动”页面中获得更多关注和重视。
不必要的嵌套是个问题,Tomasz 让我重新审视层次结构,太棒了!我更改了嵌套部分以使其更清晰。但这无关紧要。
sizeGroup
部分是个好主意,我决定在未来的开发中尽可能多地使用它,但这与我的情况无关。我没用就解决了
我在 Tomasz 的提示后发现了越来越宽的问题,但这是由于 [max!]
结合将面板添加到网格布局的第一个单元格,而不是 frame/panel嵌套。我删除了 [max!]
并将其更改为 [grow]
并且宽度不再扩大。我没有触及 p.add(panel, "cell 0 0")
部分。根据观察和定义,
p.setLayout(new MigLayout("debug, fill","[grow]","[50:20:30]10[100::]10[20::]10[50!]10[20!]"));
面板的第一行只有一列,如果我没看错的话。
在 Tomasz 编辑后编辑
我肯定比你学到的更多 :) 我试图摆脱 setBounds()
部分并将 add(panel, "cell 0 0")
更改为 add(panel, "grow")
,但我看不出有什么区别,是吗我在这里遗漏了什么? 然而 "grow"
几乎总是更好的选择和理想。
这里有 2 个 GIF 展示了我得到的东西:(来自 ScreenToGif,一个轻量级但功能强大的工具,对展示特别有用)
我使用 MigLayout
的时间很长 window。
push
选项,只有 grow
和 fill
。
这里有一个 SCCEE,正如有人曾经建议的那样,我已经忘记了他的名字:
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();
}
});
}
}
如果您 运行 代码,您会注意到列的宽度随着其包含文本长度的变化而增加。但它永远不会填满其容器的整个宽度。
可取的是,将第0列和第2列固定15%
整个宽度,让1
和3
列占据其余部分,35%
, 前两列占整个宽度的50%。
我是不是漏掉了什么?我不想指定每一列的宽度,设置 pre:min:max
,因为这是不好的做法,正如 this post 所建议的那样,它获得了很多投票。
panel.setLayout(new MigLayout("fillx",
"[left, 15%]10[left, grow, 35%]10[left, 15%]10[left, grow, 35%]",
"[center]10[center]"));
但是,如果我设置pref:min:max
,它可以填满整个宽度。
先是代码,再是解释。试试这个:
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();
}
}
我的改动说明:
现在除了简化代码和布局外,我在布局约束内使用“调试”来查看布局实际发生了什么。我建议在布局出现问题时使用它 - 它使 MigLayout
绘制组件和单元格的边界,从而可视化潜在的问题。
我删除了不必要的 mainframe
和 p
- 如果您真的需要它用于嵌套布局,请在您根据自己的喜好解决内部布局后尝试添加它。
至于 p
和 panel
- 您可能需要两种不同的布局,一个嵌套在另一个布局中,但这是问题的实际根源。 p
也有自己的网格布局,
p.add(panel,"cell 0 0");
你把 panel
放在 p
的左上角单元格中 - 这就是为什么 panel
没有分布在整个 window 而是坐在左上角的原因角落.
如您所见,没有 p
它很好地位于屏幕中间,没有任何恒定大小,仍然显示所有组件,但更重要的是它有 50% 的 window 大小用于第一列和最后两列的 50%。这是通过给组件一个“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.
而且它还可以按应有的方式调整大小!
嵌套布局也可能是另一个问题的根源——不知道你是否注意到它或者它只是没有出现在你的机器上,但如果我试图调整你的 window 即使我缩小 window,panel
变得越来越宽(从不变窄)。在某些时候,它变得比 window 本身更宽,甚至在每次调整大小时都进一步增长。
接下来 - 将尺寸设置为常量值没有意义,因为在 pack
之后布局管理器开始根据 window 及其内容的首选大小调整所有内容的大小。此外,您永远不知道用户的屏幕尺寸是多少,因此如果有效使用,任何固定尺寸都可能同样糟糕。最好通过内容和可用的运行时环境来驱动大小。在我的机器上使用你的代码,它占用了我两个屏幕 (2 x 1280) 的所有可用水平 space,并且看起来不漂亮。
我也认为你不需要使用EventQueue.invokeLater
开始框架,只需创建一个MigLayoutTest
就可以了。
在 OP 自己的回答后进行编辑
在 pack
之前使用 setBounds(0, 0, 1250, 500)
设置大小无法正常工作(我的意思是让 window 成为那个大小)。即使在 OP 自己的答案下方的屏幕截图中,它也不是 500px 高。这是我在 Windows 7 运行 JDK 1.8.0_91:
我的屏幕尺寸是 1280 x 1024,程序的尺寸 window 是 914 x 301。
我建议使用以下其中一项:
要将其设置为 1250 x 500 像素的恒定大小,请将 setSize
移动到 pack
和 setVisible
之间:
...
pack();
setSize(1250, 500);
我会使用 setSize
,setBounds
没有任何意义,因为通过调用 setLocationRelativeTo(null)
你无论如何都会在屏幕上居中程序的 window,所以origin 被立即解雇。
要水平最大化并让高度为 500 像素,请在 pack
之前设置主要 window 的首选大小:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(new Dimension(screenSize.width, 500));
并水平最大化并让首选高度保持原样:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(new Dimension(screenSize.width, getPreferredSize().height));
当然,您也可以通过设置其首选大小而不是使用 setSize
来使 window 1250 x 500 变大。
调整大小的问题现在不是那么大,但它仍然存在 - 让 window 变宽,而不是缩小它一点点。您会注意到 panel
变宽了,即使 window 变窄了。问题是 panel
组件最初不够大,无法填充 p
的一列(顺便说一句,您可以将 'debug' 标志添加到每个 MigLayout,也是 panel
- 然后它也会概述所有内部组件)。
要使其填充父容器,请像这样添加它:
p.add(panel, "cell 0 0, grow");
现在它从一开始就是 p
的全宽,并且按预期调整大小。
关于使用 invokeLater
启动 JFrame
- 我们启动我们的主要 windows 通常没有它并且从未遇到过问题,因为在第一帧之前没有与 Swing 交互可见,但我刚刚注意到它被认为是最佳实践 - 即使在 Oracle 的教程中也是如此。看来我在这里也学到了一些东西:-)。
帧的window添加和不添加"grow"
的比较测试场景:启动应用程序并将其调整为更宽。
正如您在第一个屏幕截图中看到的那样,组件尺寸小于列宽 - 看起来组件在调整大小时位于列尺寸后面。在第二个屏幕截图中,组件宽度始终与列宽保持相同。正如我之前所说,原因可能是 Java and/or 操作系统组合,我不知道。但显然它的行为有所不同,并且在我的机器上表现不佳。
感谢@Tomasz Stanczak,我终于解决了。但是,我发现他说的部分是相关的,而其他部分则不是。对于以后可能看到的读者,我必须说得更清楚一些。
最终的工作代码是:
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 MigLayoutMySCCEE 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 MigLayoutMySCCEE(){
run();
}
public void run(){
JPanel p = new JPanel();
p.setLayout(new MigLayout("debug, fill","[grow]","[50:20:30]10[100::]10[20::]10[50!]10[20!]"));
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");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
setBounds(0, 0, 1250, 500);
getContentPane().add(p);
pack();
setVisible(true);
setLocationRelativeTo(null);
setResizable(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MigLayoutMySCCEE test = new MigLayoutMySCCEE();
}
});
}
}
而 window 看起来像:
一些注意事项:
debug
技巧非常有用,促使我再次阅读 DOC。不过,我希望它能在“快速启动”页面中获得更多关注和重视。不必要的嵌套是个问题,Tomasz 让我重新审视层次结构,太棒了!我更改了嵌套部分以使其更清晰。但这无关紧要。
sizeGroup
部分是个好主意,我决定在未来的开发中尽可能多地使用它,但这与我的情况无关。我没用就解决了我在 Tomasz 的提示后发现了越来越宽的问题,但这是由于
[max!]
结合将面板添加到网格布局的第一个单元格,而不是 frame/panel嵌套。我删除了[max!]
并将其更改为[grow]
并且宽度不再扩大。我没有触及p.add(panel, "cell 0 0")
部分。根据观察和定义,p.setLayout(new MigLayout("debug, fill","[grow]","[50:20:30]10[100::]10[20::]10[50!]10[20!]"));
面板的第一行只有一列,如果我没看错的话。
在 Tomasz 编辑后编辑
我肯定比你学到的更多 :) 我试图摆脱 setBounds()
部分并将 add(panel, "cell 0 0")
更改为 add(panel, "grow")
,但我看不出有什么区别,是吗我在这里遗漏了什么? 然而 "grow"
几乎总是更好的选择和理想。
这里有 2 个 GIF 展示了我得到的东西:(来自 ScreenToGif,一个轻量级但功能强大的工具,对展示特别有用)