Java MigLayout具有绝对单元格坐标和跨距的意外布局
我有一个JPanel,可以动态添加和删除不同大小的子面板。因此,我使用具有绝对单元坐标的miglayet。在下面的例子中,结果不是我所期望的 我的代码的简化版本说明了问题,如下所示:Java MigLayout具有绝对单元格坐标和跨距的意外布局,java,swing,layout-manager,miglayout,Java,Swing,Layout Manager,Miglayout,我有一个JPanel,可以动态添加和删除不同大小的子面板。因此,我使用具有绝对单元坐标的miglayet。在下面的例子中,结果不是我所期望的 我的代码的简化版本说明了问题,如下所示: import java.awt.Color; import java.awt.Dimension; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; import net.miginfoco
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutDemo
{
private static final int CELL_WIDTH = 60;
private static final int CELL_HEIGHT = 50;
public static JPanel createBigPanel()
{
JPanel bigSubPanel = new JPanel();
bigSubPanel.setPreferredSize(new Dimension(3 * CELL_WIDTH, 2 * CELL_HEIGHT));
bigSubPanel.setBorder(BorderFactory.createLineBorder(Color.black));
bigSubPanel.setBackground(Color.LIGHT_GRAY);
return bigSubPanel;
}
public static JPanel createSmallPanel()
{
JPanel smallSubPanel = new JPanel();
smallSubPanel.setPreferredSize(new Dimension(2 * CELL_WIDTH, CELL_HEIGHT));
smallSubPanel.setBorder(BorderFactory.createLineBorder(Color.black));
smallSubPanel.setBackground(Color.LIGHT_GRAY);
return smallSubPanel;
}
public static JPanel createCellPanel()
{
JPanel cellSubPanel = new JPanel();
cellSubPanel.setPreferredSize(new Dimension(CELL_WIDTH, CELL_HEIGHT));
cellSubPanel.setBackground(Color.LIGHT_GRAY);
return cellSubPanel;
}
private static void createAndShowGUI()
{
//Create and set up the window.
JFrame frame = new JFrame("MigLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
// main panel where the sub-panels are placed in
JPanel mainPanel = new JPanel();
MigLayout mg = new MigLayout("debug, gap 0 0");
mainPanel.setLayout(mg);
mainPanel.add(createBigPanel(), "cell 0 0 3 2"); // [col row [span x [span y]]]
mainPanel.add(createBigPanel(), "cell 3 0 3 2");
mainPanel.add(createSmallPanel(), "cell 6 0 2 1, align left top");
mainPanel.add(createSmallPanel(), "cell 6 1 2 1, align left top");
mainPanel.add(createSmallPanel(), "cell 0 2 2 1, align left top");
mainPanel.add(createBigPanel(), "cell 2 2 3 2");
// problem occurs
mainPanel.add(createBigPanel(), "cell 5 2 3 2");
// mainPanel.add(createCellPanel(), "cell 0 4 1 1");
// mainPanel.add(createCellPanel(), "cell 1 4 1 1");
// mainPanel.add(createCellPanel(), "cell 2 4 1 1");
// mainPanel.add(createCellPanel(), "cell 3 4 1 1");
// mainPanel.add(createCellPanel(), "cell 4 4 1 1");
// mainPanel.add(createCellPanel(), "cell 5 4 1 1");
// mainPanel.add(createCellPanel(), "cell 6 4 1 1");
// mainPanel.add(createCellPanel(), "cell 7 4 1 1");
frame.getContentPane().add(mainPanel);
frame.setResizable(false);
frame.pack();
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
}
如果我删除代码行mainPanel.add(createBigPanel(),“cell 5 2 3 2”)代码>一切都如我所料。但是,当我在第5列和第2行中添加面板时,面板似乎被放置在第5列和第6列之间的额外列中
如果我还添加代码行
mainPanel.add(createCellPanel(), "cell 0 4 1 1");
mainPanel.add(createCellPanel(), "cell 1 4 1 1");
mainPanel.add(createCellPanel(), "cell 2 4 1 1");
mainPanel.add(createCellPanel(), "cell 3 4 1 1");
mainPanel.add(createCellPanel(), "cell 4 4 1 1");
mainPanel.add(createCellPanel(), "cell 5 4 1 1");
mainPanel.add(createCellPanel(), "cell 6 4 1 1");
mainPanel.add(createCellPanel(), "cell 7 4 1 1");
问题似乎已“修复”,所有内容都放在正确的列和行中
我怀疑我的问题与细胞的跨度有关。
我是否缺少一些布局约束或参数?或者它是MigLayout库中的一个bug
我目前正在java 7中使用MigLayout V4.0。我还使用V5.0快照测试了我的代码,但结果是一样的。该示例按预期工作。看起来只有一个附加列。
面板2和面板7是左对齐的,因此看起来好像还有另一列。
将约束置于面板2和面板2的中心将显示面板
我们只是左对齐,没有创建其他列
那么,当你添加8个小面板时,为什么它突然起作用呢?MIG布局的
不知道如果被要求跨越三个区域,它应该占据多少空间
列——直到这三列存在。因此,通过添加这些小面板
告诉经理您对spanx 2
,spanx 3
约束的期望。
(在本例中,这些是单元格
约束的第三个参数。)
还请注意,最好使用w
和h
约束,而不是
通过setPreferredSize()
方法指定大小
我已经创建了一个修改过的示例,在该示例中,我使用标签而不是面板
更好的视觉理解:
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutDemo2 extends JFrame {
public MigLayoutDemo2() {
initUI();
}
private void initUI() {
JPanel pnl = new JPanel(new MigLayout("gap 0"));
pnl.add(createLabel("One"), "cell 0 0 3 2, w 180, h 100");
pnl.add(createLabel("Two"), "cell 3 0 3 2, w 180, h 100, center");
pnl.add(createLabel("Three"), "cell 6 0 2 1, align left top, w 120, h 50");
pnl.add(createLabel("Four"), "cell 6 1 2 1, align left top, w 120, h 50");
pnl.add(createLabel("Five"), "cell 0 2 2 1, align left top, w 120, h 50");
pnl.add(createLabel("Six"), "cell 2 2 3 2, w 180, h 100");
pnl.add(createLabel("Seven"), "cell 5 2 3 2, center, w 180, h 100");
// pnl.add(createLabel("A"), "cell 0 4 1 1, w 60, h 50");
// pnl.add(createLabel("A"), "cell 1 4 1 1, w 60, h 50");
// pnl.add(createLabel("A"), "cell 2 4 1 1, w 60, h 50");
// pnl.add(createLabel("A"), "cell 3 4 1 1, w 60, h 50");
// pnl.add(createLabel("A"), "cell 4 4 1 1, w 60, h 50");
// pnl.add(createLabel("A"), "cell 5 4 1 1, w 60, h 50");
// pnl.add(createLabel("A"), "cell 6 4 1 1, w 60, h 50");
// pnl.add(createLabel("A"), "cell 7 4 1 1, w 60, h 50");
add(pnl);
pack();
setTitle("MigLayout example");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private JLabel createLabel(String text) {
JLabel lbl = new JLabel(text, JLabel.CENTER);
lbl.setBorder(BorderFactory.createEtchedBorder());
return lbl;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MigLayoutDemo2 ex = new MigLayoutDemo2();
ex.setVisible(true);
}
});
}
}
在以下示例中,标签2和7居中。如果
左对齐,看起来标签7位于单独的列中
但事实并非如此
通过在末尾添加8个小面板,我们告诉经理
布局应该是什么样子的:
编辑1
根据评论的解决方案。我采取了另一种方法。我达到了要求
带拆分单元格的布局:
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutDemo3 extends JFrame {
public MigLayoutDemo3() {
initUI();
}
private void initUI() {
JPanel pnl = new JPanel(new MigLayout("gap 0 0"));
pnl.add(createLabel("One"), "gapright 0, w 180, h 100, split 2");
pnl.add(createLabel("Two"), "w 180, h 100");
pnl.add(createLabel("Three"), "split 2, flowy, w 120, h 50, gapbottom 0");
pnl.add(createLabel("Four"), "w 120, h 50, wrap");
pnl.add(createLabel("Five"), "top, gapright 0, split 3, span 3, w 120, h 50");
pnl.add(createLabel("Six"), "gapright 0, w 180, h 100");
pnl.add(createLabel("Seven"), "w 180, h 100");
add(pnl);
pack();
setTitle("MigLayout example");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private JLabel createLabel(String text) {
JLabel lbl = new JLabel(text, JLabel.CENTER);
lbl.setBorder(BorderFactory.createEtchedBorder());
return lbl;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MigLayoutDemo3 ex = new MigLayoutDemo3();
ex.setVisible(true);
}
});
}
}
还有其他解决办法
对我有效的解决方案是在MIG布局中使用绝对定位,即组件约束,形式为pos x y[x2][y2]
:
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutDemo4 extends JFrame {
private static final int CELL_WIDTH = 60;
private static final int CELL_HEIGHT = 50;
public MigLayoutDemo4() {
initUI();
}
private void initUI() {
JPanel pnl = new JPanel(new MigLayout("gap 0 0"));
pnl.add(createLabel("One"), "pos 0 0");
pnl.add(createLabel("Two"), "pos "+(CELL_WIDTH * 3)+" "+(CELL_HEIGHT * 0));
pnl.add(createLabel("Three"), "pos "+(CELL_WIDTH * 6)+" "+(CELL_HEIGHT * 0));
pnl.add(createLabel("Four"), "pos "+(CELL_WIDTH * 6)+" "+(CELL_HEIGHT * 1));
pnl.add(createLabel("Five"), "pos "+(CELL_WIDTH * 0)+" "+(CELL_HEIGHT * 2));
pnl.add(createLabel("Six"),"pos "+(CELL_WIDTH * 2)+" "+(CELL_HEIGHT * 2));
pnl.add(createLabel("Seven"), "pos "+(CELL_WIDTH * 5)+" "+(CELL_HEIGHT * 2));
add(pnl);
pack();
setTitle("MigLayout example");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private JLabel createLabel(String text) {
JLabel lbl = new JLabel(text, JLabel.CENTER);
lbl.setBorder(BorderFactory.createEtchedBorder());
return lbl;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MigLayoutDemo3 ex = new MigLayoutDemo3();
ex.setVisible(true);
}
});
}
}
我不明白的是,为什么柱子会变得比需要的更大。因为标签7正好适合第6-8列中的空间(与添加之前一样)。你能不能建议一种方法,在不添加8个小面板的情况下,获得与上一张图片相同的结果?我试图将每个列的大小定义为列约束,但结果是面板的宽度始终为8*60。我需要的是一个始终具有所需最小尺寸的面板。感谢您的建议和提示。您的解决方案工作正常。不幸的是,考虑到我想在主面板中动态添加和删除子面板,它没有那么灵活。