我有一个由按钮(X),标签(Y)和进度条(Z)组成的面板。理想情况下,我想这样做:
| X-X Y---------------Y Z---Z ============= | <-- expanded-size panel
^ extra space
| X-X Y------Y Z---Z | <-- reduced-size panel
上图显示:
但是,当我尝试使用GroupLayout时,这就是扩展面板时会发生的情况:
| X-X Y---------------Y ============= Z---Z | <-- expanded-size panel (bad)
问题是,当面板有额外的空间时,标签(Y)会扩展到超出需要的范围,这会将进度条(Z)推向右侧。我希望进度条的(Z)位置在标签(Y)旁边。
如何完成此布局?
示例代码(“Blah.java”):
import java.awt.*;
import javax.swing.*;
public class Blah extends JPanel {
public Blah() {
final JButton X = new JButton("X");
final JLabel Y = new JLabel("yyyyyyyyyyy");
Y.setOpaque(true);
Y.setBackground(Color.YELLOW);
final JProgressBar Z = new JProgressBar();
Z.setIndeterminate(true);
final GroupLayout l = new GroupLayout(this);
super.setLayout(l);
l.setHorizontalGroup(
l.createSequentialGroup()
.addComponent(X, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(Y, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(Z, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE));
l.setVerticalGroup(
l.createParallelGroup()
.addComponent(X)
.addComponent(Y)
.addComponent(Z));
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final JFrame frame = new JFrame("Blah");
frame.add(new Blah());
frame.pack();
frame.setVisible(true);
}
});
}
}
答案 0 :(得分:4)
一个单独的布局管理器很少能满足您的所有需求。相反,您可以使用复合布局方法。
也就是说,将每个单独的布局要求分成一个单独的组件,并使用它自己的布局管理器。然后将所有这些添加到主组件中,管理总体要求。
作为一个例子
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class SimpleGridBagLayout {
public static void main(String[] args) {
new SimpleGridBagLayout();
}
public SimpleGridBagLayout() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
add(createLabel("XXX-XXX", Color.BLUE), gbc);
JPanel panel = new JPanel();
panel.add(createLabel("Y-Y", Color.RED));
panel.add(createLabel("ZZZZZ---ZZZZZ", Color.GREEN), gbc);
gbc.gridx++;
gbc.weightx = 1;
add(panel, gbc);
}
protected JLabel createLabel(String text, Color border) {
JLabel label = new JLabel(text);
label.setBorder(new LineBorder(border));
return label;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 100);
}
}
}
这里有很多因素在起作用。当可用大小较小时,子组件的首选大小和最小大小将对某些布局管理器如何布局组件产生重大影响。
<强>更新强>
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
add(createLabel("XXX-XXX", Color.BLUE), gbc);
JPanel panel = new JPanel(new GridBagLayout());
gbc = new GridBagConstraints();
gbc.gridx = 0;
panel.add(createLabel("Y-Y", Color.RED), gbc);
gbc.gridx = 1;
panel.add(createLabel("ZZZZZ---ZZZZZ", Color.GREEN), gbc);
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.weightx = 1;
add(panel, gbc);
}
<强>更新强>
现在进行“非缩小”进度条
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
add(createLabel("XXX-XXX", Color.BLUE), gbc);
JPanel panel = new JPanel(new GridBagLayout());
gbc = new GridBagConstraints();
gbc.gridx = 0;
panel.add(createLabel("Y-Y", Color.RED), gbc);
gbc.gridx = 1;
MyProgressBar pb = new MyProgressBar();
panel.add(pb, gbc);
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.weightx = 1;
add(panel, gbc);
}
protected JLabel createLabel(String text, Color border) {
JLabel label = new JLabel(text);
label.setBorder(new LineBorder(border));
return label;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 100);
}
}
public class MyProgressBar extends JProgressBar {
@Override
public Dimension getPreferredSize() {
Dimension ps = super.getPreferredSize();
ps.width = 75;
return ps;
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
}
答案 1 :(得分:0)
在我的头撞到墙上太久之后,我在SpringLayout
的教程(http://docs.oracle.com/javase/tutorial/uiswing/layout/spring.html)中发现了这个小文档:
当组件的
getMaximumSize
和getPreferredSize
方法返回相同的值时,SpringLayout
会将此解释为意味着组件不应被拉伸。
因此,使用SpringLayout
并手动设置Y
和Z
的最大尺寸,可以实现上述理想布局。这是代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Blah extends JPanel {
public Blah() {
final JButton X = new JButton("X");
final JLabel Y = new JLabel("yyyyyyyyyyy");
Y.setOpaque(true);
Y.setBackground(Color.YELLOW);
final JProgressBar Z = new JProgressBar();
Z.setIndeterminate(true);
final SpringLayout l = new SpringLayout();
super.setLayout(l);
super.add(X);
super.add(Y);
super.add(Z);
Z.setMaximumSize(Z.getPreferredSize());
l.putConstraint(SpringLayout.WEST, X, 10, SpringLayout.WEST, this);
l.putConstraint(SpringLayout.WEST, Y, 10, SpringLayout.EAST, X);
l.putConstraint(SpringLayout.WEST, Z, 10, SpringLayout.EAST, Y);
l.putConstraint(SpringLayout.EAST, this, 10, SpringLayout.EAST, Z);
l.putConstraint(SpringLayout.NORTH, X, 10, SpringLayout.NORTH, this);
l.putConstraint(SpringLayout.NORTH, Y, 10, SpringLayout.NORTH, this);
l.putConstraint(SpringLayout.NORTH, Z, 10, SpringLayout.NORTH, this);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final JFrame frame = new JFrame("Blah");
frame.add(new Blah());
frame.pack();
frame.setVisible(true);
}
});
}
}