好的,你不小心遇到了一个怪癖。虽然布局看起来很简单,但它
我也花了一些时间来解决这个问题。
(顺便说一句,水平拉伸按钮并不是最佳的 UI 设计。)
原因在于管理人员的构建方式。如果布局不包含 at
连续至少两个组件,不可能跨越一个组件。
您的布局仅包含一列,因此,设置 widthx > 1 确实
不行。有两种方法可以解决这个问题:我们可以放置一些
虚拟组件进入布局,或者我们可以在前后放置一些空间
减小宽度的区域。
我提供了三种解决方案:a) 带有虚拟标签的 GridBagLayout,b) GridBagLayout
带插图和 c) 带间隙的 MigLayout。
解决方案 1
package com.zetcode;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class FillingCards extends JPanel {
private JTextArea question;
private JTextArea answer;
private JButton button;
private JLabel label;
public FillingCards() {
setupGUI();
}
private void setupGUI() {
question = new JTextArea(12, 22);
answer = new JTextArea(12, 22);
button = new JButton("Next");
label = new JLabel("Answer");
question.setBorder(
BorderFactory.createEtchedBorder()
);
answer.setBorder(
BorderFactory.createEtchedBorder()
);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = 1;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.insets = new Insets(5, 10, 5, 10);
gbc.gridx = 1;
gbc.gridy = 0;
add(question, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 1;
gbc.gridy = 1;
gbc.weighty = 0;
gbc.weightx = 0;
add(label, gbc);
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 1;
gbc.gridy = 2;
gbc.weightx = 1;
gbc.weighty = 1;
add(answer, gbc);
gbc.gridwidth = 3;
gbc.weightx = 1;
gbc.weighty = 0;
gbc.gridx = 0;
gbc.gridy = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(button, gbc);
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 1;
gbc.weighty = 0;
gbc.weightx = 0;
gbc.gridx = 0;
gbc.gridy = 3;
add(new JLabel(" "), gbc);
gbc.gridx = 2;
gbc.gridy = 3;
add(new JLabel(" "), gbc);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Quiz cards");
FillingCards card = new FillingCards();
frame.add(BorderLayout.CENTER, card);
frame.pack();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
在“下一步”按钮下方的第一个和第三个单元格中放置了两个标签。
这不是一个干净的解决方案,主要是为了演示问题而创建的。
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 1;
gbc.weighty = 0;
gbc.weightx = 0;
gbc.gridx = 0;
gbc.gridy = 3;
add(new JLabel(" "), gbc);
gbc.gridx = 2;
gbc.gridy = 3;
add(new JLabel(" "), gbc);
创建了两个虚拟标签。这些标签的宽度决定
左右间隙的宽度。
解决方案 2
package com.zetcode;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class FillingCards2 extends JPanel {
private JTextArea question;
private JTextArea answer;
private JButton button;
private JLabel label;
public FillingCards2() {
setupGUI();
}
private void setupGUI() {
question = new JTextArea(12, 22);
answer = new JTextArea(12, 22);
button = new JButton("Next");
label = new JLabel("Answer");
question.setBorder(
BorderFactory.createEtchedBorder()
);
answer.setBorder(
BorderFactory.createEtchedBorder()
);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.insets = new Insets(5, 15, 5, 15);
gbc.gridx = 1;
gbc.gridy = 0;
add(question, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 1;
gbc.gridy = 1;
gbc.weighty = 0;
gbc.weightx = 0;
add(label, gbc);
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 1;
gbc.gridy = 2;
gbc.weightx = 1;
gbc.weighty = 1;
add(answer, gbc);
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.gridwidth = 3;
gbc.weightx = 1;
gbc.weighty = 0;
gbc.gridx = 0;
gbc.gridy = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(button, gbc);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Quiz cards");
FillingCards2 card = new FillingCards2();
frame.add(BorderLayout.CENTER, card);
frame.pack();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
在本例中,我们使用insets 属性来创建所需的
布局。标签和文本区域的左右插图更宽
那些按钮。
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.gridwidth = 3;
gbc.weightx = 1;
gbc.weighty = 0;
gbc.gridx = 0;
gbc.gridy = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(button, gbc);
左右插图从 15px 更改为 5px。这样我们实现
该按钮比其他组件更宽。
解决方案 3
第三个解决方案是使用MigLayout 管理器创建的。我们需要更少
创建布局的代码。
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import net.miginfocom.swing.MigLayout;
public class MigLayoutFillingCards extends JFrame {
public MigLayoutFillingCards() {
initUI();
setTitle("Quiz cards");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
setLayout(new MigLayout("wrap"));
JTextArea area1 = new JTextArea();
JTextArea area2 = new JTextArea();
area1.setBorder(
BorderFactory.createEtchedBorder()
);
area2.setBorder(
BorderFactory.createEtchedBorder()
);
JLabel label = new JLabel("Answer");
JButton btn = new JButton("Next");
add(area1, "w 250, h 150, grow, push, gap 15 15 0 0");
add(label, "gap 15 15 0 0");
add(area2, "w 250, h 150, grow, push, gap 15 15 0 0");
add(btn, "growx, pushx");
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MigLayoutFillingCards ex = new MigLayoutFillingCards();
ex.setVisible(true);
}
});
}
}
所需的布局是使用gap 约束创建的,它添加了额外的
组件两侧的空间。