我正在制作一个在容器中使用GridBagLayout的程序。我的主要用途是拥有两个JPanel,它占据窗口水平空间的75%和25%。但是出于某种原因,这两个面板看起来更像90/10,并且在调整大小时,较小的面板会迅速改变尺寸,在它的表观最小尺寸和我认为理想的25%之间。
以下是相关代码。
frmReedreadV = new JFrame();
frmReedreadV.setBounds(x, y, width, height);
frmReedreadV.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmReedreadV.getContentPane().setLayout(new BoxLayout(frmReedreadV.getContentPane(), BoxLayout.Y_AXIS));
JPanel stretchyPanel = new JPanel();
frmReedreadV.getContentPane().add(stretchyPanel);
stretchyPanel.setLayout(new CardLayout(0, 0));
JPanel textAndUsers = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weighty = 1;
textArea = new JTextArea();
textArea.setMargin(new Insets(2, 5, 5, 2));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
scrollPane = new JScrollPane(textArea);
scrollPane.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
gbc.weightx = 0.8;
textAndUsers.add(scrollPane, gbc);
list = new FriendsList(listUpdate);
gbc.weightx = 0.2;
textAndUsers.add(list.frmUserList, gbc);
stretchyPanel.add(textAndUsers);
FriendsList是JPanel中包含的JList。
主CardLayout内容窗格中还有其他按钮和文本字段,但那些不应该影响此GridBagLayout内部的内容,对吗?
我将此JPanel的另一个副本作为独立应用程序制作,并且它完美地显示和调整大小。见这里:
JFrame frame = new JFrame();
frame.getContentPane().setLayout((new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS)));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(100, 100, 550, 600);
JPanel stretchyPane = new JPanel();
frame.getContentPane().add(stretchyPane);
stretchyPane.setLayout(new CardLayout(0, 0));
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
JTextArea text = new JTextArea();
text.setMargin(new Insets(2, 5, 5, 2));
JScrollPane panel1 = new JScrollPane(text);
FriendsList panel2 = new FriendsList(new Object());
c.fill = GridBagConstraints.BOTH;
c.weightx = .8;
c.weighty = 1;
panel.add(panel1, c);
c.weightx = .2;
//c.fill = GridBagConstraints.HORIZONTAL;
panel.add(panel2.frmUserList, c);
stretchyPane.add(panel);
frame.setVisible(true);
由于我已将原始行逐行复制到副本中,可能导致两者之间存在差异?
答案 0 :(得分:1)
weightx和weighty属性似乎可以作为比例大小,但这不是他们所做的。实际上,它们决定了布局中额外空间的分布。
如果通过在JFrame上调用pack()将所有内容设置为首选大小,则不会有额外空间。这意味着weightx和weighty属性在该状态下没有任何效果。
一旦用户开始调整窗口大小,就会有额外的空间,然后GridBagLayout才会查询weightx和weighty属性,以确定如何将额外空间分配给每个列和行。在此之前,如果它们的首选尺寸决定了,那么重量较小的部件完全有可能比具有较大重量的部件宽。
希望这个简单的程序能够展示这个概念。尝试使用鼠标(或键盘)将窗口调整为更宽,并观察每个文本字段的增长情况:
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GridBagProportions {
static void buildAndShowWindow() {
JTextField small = new JTextField("small (0.8)", 5);
JTextField large = new JTextField("LARGE (0.2)", 30);
small.setMinimumSize(small.getPreferredSize());
large.setMinimumSize(large.getPreferredSize());
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets.left = 6;
gbc.insets.top = 6;
gbc.insets.bottom = 6;
gbc.weightx = 0.8;
panel.add(small, gbc);
gbc.weightx = 0.2;
gbc.insets.right = 6;
panel.add(large, gbc);
JFrame frame = new JFrame("GridBagLayout Proportions");
frame.getContentPane().add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
buildAndShowWindow();
}
});
}
}
那么可以做些什么呢?嗯,这是GridBagLayout无法做到的一种布局方案。我会尝试使用SpringLayout:
SpringLayout layout = new SpringLayout();
JPanel textAndUsers = new JPanel(layout);
SpringLayout.Constraints scrollPaneConstraints =
new SpringLayout.Constraints(scrollPane);
Spring scrollPaneWidth = scrollPaneConstraints.getWidth();
SpringLayout.Constraints listConstraints =
new SpringLayout.Constraints(scrollPaneWidth,
scrollPaneConstraints.getY(),
Spring.scale(scrollPaneWidth, 0.25f),
scrollPaneConstraints.getHeight());
layout.putConstraint(SpringLayout.EAST, textAndUsers, 0,
SpringLayout.EAST, frmUserList);
layout.putConstraint(SpringLayout.SOUTH, textAndUsers, 0,
SpringLayout.SOUTH, scrollPane);
textAndUsers.add(scrollPane, scrollPaneConstraints);
textAndUsers.add(frmUserList, listConstraints);
请注意,listConstraints的创建指定了宽度参数Spring.scale(scrollPaneWidth, 0.25f)
。这样可以确保列表的宽度始终是包含JTextArea的scrollPane的四分之一。
SpringLayout使用起来很棘手,因为你必须确保明确地将布局容器的远边链接到子组件,因为SpringLayout不会增长以自动容纳所有子组件。这就是putConstraint调用的内容。