如何解决摆动:没有MigLayout的垂直堆叠组件
| 我终于得到了我想要的垂直堆叠组件的行为,这些组件的首选高度随时间变化。但是我需要使用MigLayout。 有没有MigLayout的方法吗? (它是针对图书馆的,除非有必要,否则我不想强制依赖) 这是我正在寻找的行为(我的测试程序可以实现): 在垂直顺序中,有一个调整大小的按钮,即“空白空间”(嗯,一个JLabel标记为这样),一个红色矩形和一个绿色正方形。调整大小按钮的高度固定。红场具有随机大小,可以在任意时间更改。绿色正方形设置其首选高度以匹配其宽度,我想扩展其宽度以填充容器。空空间会水平和垂直扩展,以填充容器中的剩余空间。 什么可以代替MigLayout工作?import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class AutoResizeDemo extends JPanel
{
static private class ResizingPanel extends JPanel
{
final private Color color;
private Dimension dpref = new Dimension(100,100);
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.setColor(this.color);
g.fillRect(0,w,h);
g.setColor(Color.BLACK);
g.drawRect(0,w-1,h-1);
String s = this.dpref.width+\"x\"+this.dpref.height;
FontMetrics fm = g.getFontMetrics();
g.drawString(s,fm.getHeight());
}
public ResizingPanel(Color color,boolean isSquare)
{
this.color = color;
if (isSquare)
{
addComponentListener(new ComponentAdapter() {
@Override public void componentResized(ComponentEvent e) {
doResize(getWidth(),getWidth());
}
});
}
}
@Override public Dimension getPreferredSize() {
return this.dpref;
}
public void doResize(int w,int h)
{
this.dpref = new Dimension(w,h);
revalidate();
}
}
public AutoResizeDemo()
{
super(new MigLayout(\"\",\"[grow]\",\"\"));
setPreferredSize(new Dimension(200,800));
final ResizingPanel resizingPanelRandom = new ResizingPanel(Color.RED,false);
ResizingPanel resizingPanelSquare = new ResizingPanel(Color.GREEN,true);
JPanel buttonPanel = new JPanel(new FlowLayout());
final Random rand = new Random();
addButton(buttonPanel,\"resize\",new Runnable() {
@Override public void run() {
resizingPanelRandom.doResize(
rand.nextInt(100)+100,rand.nextInt(100)+100
);
}
});
add(buttonPanel,\"wrap\");
JLabel spaceLabel = new JLabel(\"empty space\");
spaceLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(spaceLabel,\"push,grow,wrap\");
add(resizingPanelRandom,\"wrap\");
add(resizingPanelSquare,\"pushx,growx,wrap\");
}
private void addButton(JPanel panel,String title,final Runnable r) {
JButton button = new JButton(title);
button.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
r.run();
}
});
panel.add(button);
}
public static void main(String[] args) {
JFrame frame = new JFrame(AutoResizeDemo.class.getSimpleName());
frame.setContentPane(new AutoResizeDemo());
frame.pack();
frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
解决方法
您可以使用
SpringLayout
解决此问题,方法是将所有组件连接在一起并连接到其容器的边缘。
按键面板
按钮面板的左侧和顶部到容器面板的左侧和顶部
绿色面板
容器面板的左侧,右侧和底部,左侧,右侧和底部
红色面板
容器面板的左到左和绿色面板的底部到顶部
空间标签
按钮面板的顶部至南部,容器面板的左侧,右侧,左侧和右侧,红色面板的底部至顶部
编辑:我爱SpringLayout,没有什么不能做的。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SpringLayout;
public class AutoResizeDemo2 extends JPanel {
static private class ResizingPanel extends JPanel {
final private Color color;
private Dimension dpref = new Dimension(100,100);
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.setColor(this.color);
g.fillRect(0,w,h);
g.setColor(Color.BLACK);
g.drawRect(0,w - 1,h - 1);
String s = this.dpref.width + \"x\" + this.dpref.height;
FontMetrics fm = g.getFontMetrics();
g.drawString(s,fm.getHeight());
}
public ResizingPanel(Color color,boolean isSquare) {
this.color = color;
if (isSquare) {
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
doResize(getWidth(),getWidth());
}
});
}
}
@Override
public Dimension getPreferredSize() {
return this.dpref;
}
public void doResize(int w,int h) {
this.dpref = new Dimension(w,h);
revalidate();
}
}
public AutoResizeDemo2() {
SpringLayout layout = new SpringLayout();
setLayout(layout);
setPreferredSize(new Dimension(200,800));
final ResizingPanel resizingPanelRandom = new ResizingPanel(Color.RED,false);
ResizingPanel resizingPanelSquare = new ResizingPanel(Color.GREEN,true);
JPanel buttonPanel = new JPanel(new FlowLayout());
final Random rand = new Random();
addButton(buttonPanel,\"resize\",new Runnable() {
@Override
public void run() {
resizingPanelRandom.doResize(rand.nextInt(100) + 100,rand.nextInt(100) + 100);
}
});
add(buttonPanel);
layout.putConstraint(SpringLayout.NORTH,buttonPanel,5,SpringLayout.NORTH,this);
layout.putConstraint(SpringLayout.WEST,SpringLayout.WEST,this);
JLabel spaceLabel = new JLabel(\"empty space\");
spaceLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(resizingPanelSquare);
layout.putConstraint(SpringLayout.SOUTH,resizingPanelSquare,-5,SpringLayout.SOUTH,this);
layout.putConstraint(SpringLayout.EAST,SpringLayout.EAST,this);
add(resizingPanelRandom);
layout.putConstraint(SpringLayout.SOUTH,resizingPanelRandom,resizingPanelSquare);
layout.putConstraint(SpringLayout.WEST,this);
add(spaceLabel);
layout.putConstraint(SpringLayout.NORTH,spaceLabel,buttonPanel);
layout.putConstraint(SpringLayout.WEST,this);
layout.putConstraint(SpringLayout.SOUTH,resizingPanelRandom);
}
private void addButton(JPanel panel,String title,final Runnable r) {
JButton button = new JButton(title);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
r.run();
}
});
panel.add(button);
}
public static void main(String[] args) {
JFrame frame = new JFrame(AutoResizeDemo2.class.getSimpleName());
frame.setContentPane(new AutoResizeDemo2());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
, 使用BoxLayout。
您可以将Box.createVerticalGlue()用于空白空间。
BoxLayout遵循组件的最大大小,因此您可能需要重写getMaximumSize()方法以返回红色和绿色框的首选大小。
对于绿色框,您还需要重写getPreferredSize()以使高度与宽度保持同步。
, 如果不进行大量分析,很难确定SpringLayout的布局。尝试使用TableLayout。布局中唯一棘手的部分是绿色方块的高度等于其宽度。对于布局管理器来说,这有点不寻常,因此我只是特例。一个可运行的示例:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.esotericsoftware.tablelayout.swing.Table;
public class Test extends JFrame {
JButton button;
JPanel red,green;
public Test () {
button = new JButton(\"Resize\");
button.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
red.setPreferredSize(new Dimension(138,new Random().nextInt(190) + 10));
red.revalidate();
}
});
red = new JPanel();
red.setPreferredSize(new Dimension(138,145));
red.setBackground(Color.red);
green = new JPanel();
green.setPreferredSize(new Dimension(100,100));
green.setBackground(Color.green);
// The DSL can be much easier to describe complex hierarchies.
boolean dsl = false;
if (dsl)
dsl();
else
javaApi();
setSize(160,400);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
private void javaApi () {
final Table table = new Table() {
public void layout () {
green.setPreferredSize(new Dimension(getWidth(),getWidth()));
super.layout();
}
};
table.pad(10).defaults().left().space(5);
table.addCell(button);
table.row();
table.addCell().expandY();
table.row();
table.addCell(red);
table.row();
table.addCell(green).expandX().fillX();
getContentPane().add(table);
}
private void dsl () {
final Table table = new Table() {
public void layout () {
green.setPreferredSize(new Dimension(getWidth(),getWidth()));
super.layout();
}
};
table.register(\"button\",button);
table.register(\"red\",red);
table.register(\"green\",green);
table.parse(\"pad:10 * left space:5 \" //
+ \"[button] ---\" //
+ \"[] expandy ---\" //
+ \"[red] ---\" //
+ \"[green] expandx fillx\" //
);
getContentPane().add(table);
}
public static void main (String[] args) throws Exception {
new Test();
}
}
基于表,很容易一目了然地了解布局。我提供了使用Java API和DSL的代码。自完成后,Java API很不错。这只是布局代码:
table.pad(10).defaults().left().space(5);
table.addCell(button);
table.row();
table.addCell().expandY();
table.row();
table.addCell(red);
table.row();
table.addCell(green).expandX().fillX();
DSL非常适合描述层次结构,此示例可能不需要。不幸的是,Java没有逐字字符串,尽管可以在文件中描述较大的UI。对于此示例,不带Java字符串引号的DSL将为:
pad:10 * left space:5
[button]
---
[] expandy
---
[red]
---
[green] expandx fillx
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。