我搜索了一下,并没有找到一个很好的答案来解决我的问题。
我正在开发一个必须可调整大小的 gui。它包含一个JTextArea
位于JScrollPane
. 这是我的问题。只要我不手动调整 JFrame 的大小,就会保留“初始”布局并且一切看起来都很好。一旦我手动调整大小(如果JTextArea
已经处于滚动模式),布局就会变得混乱。
这是一个 SSCCE(我在保留代码结构的同时去掉了大部分部分。我希望这样更具可读性):
import java.awt.Color;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import net.miginfocom.swing.MigLayout;
public class Tab extends JFrame {
private static final long serialVersionUID = 1L;
private JTextArea messageTextArea;
private JPanel optionPanel, messagePanel;
private JTabbedPane plotTabPane;
public static void main(String[] args) {
final Tab tab = new Tab();
tab.setSize(1000, 600);
tab.setVisible(true);
new Thread(new Runnable() {
@Override
public void run() {
int count = 0;
tab.printRawMessage("start");
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {}
tab.printRawMessage("\ntestMessage" + count++);
}
}
}).start();
}
public Tab() {
super();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents();
}
private void initComponents() {
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new MigLayout("insets 0", "", ""));
mainPanel.add(getLeftTopPanel(), "shrinky, top, w 450!");
mainPanel.add(getRightPanel(), "spany 5, wrap, grow, pushx, wmin 400");
mainPanel.add(getMessagePanel(), "pushy, growy, w 450!");
JScrollPane contentScrollPane = new JScrollPane(mainPanel);
contentScrollPane.setBorder(BorderFactory.createEmptyBorder());
setContentPane(contentScrollPane);
}
protected JPanel getLeftTopPanel() {
if (optionPanel == null) {
optionPanel = new JPanel();
optionPanel.setBorder(BorderFactory.createTitledBorder(null, "Configuration", TitledBorder.LEFT, TitledBorder.TOP, new Font("null", Font.BOLD, 12), Color.BLUE));
optionPanel.setLayout(new MigLayout("insets 0", "", "top, align 50%"));
JLabel label = new JLabel("Choose");
label.setHorizontalAlignment(JLabel.RIGHT);
optionPanel.add(label, "w 65!");
optionPanel.add(new JSeparator(JSeparator.VERTICAL), "spany 5, growy, w 2!");
optionPanel.add(new JComboBox(new String[] {"option1", "option2", "option3"}), "span, growx, wrap");
optionPanel.add(new JLabel("Type"), "right");
optionPanel.add(new JTextField("3"), "w 65!, split 2");
optionPanel.add(new JLabel("Unit"), "wrap");
optionPanel.add(new JLabel("Slide"), "right");
optionPanel.add(new JSlider(0, 100), "span, growx, wrap");
}
return optionPanel;
}
protected JTabbedPane getRightPanel() {
if (plotTabPane == null) {
plotTabPane = new JTabbedPane();
plotTabPane.add("Tab1", new JPanel());
plotTabPane.add("Tab2", new JPanel());
}
return plotTabPane;
}
protected JPanel getMessagePanel() {
if (messagePanel == null) {
messagePanel = new JPanel();
messagePanel.setBorder(BorderFactory.createTitledBorder(null, "Status Console", TitledBorder.LEFT, TitledBorder.TOP, new Font("null", Font.BOLD, 12), Color.BLUE));
messagePanel.setLayout(new MigLayout("insets 0", "", "top, align 50%"));
messagePanel.add(new JScrollPane(getMessageTextArea()), "push, grow");
}
return messagePanel;
}
protected JTextArea getMessageTextArea() {
if (messageTextArea == null) {
messageTextArea = new JTextArea();
messageTextArea.setEditable(false);
messageTextArea.setFont(new Font(null, Font.PLAIN, 20));
messageTextArea.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
}
return messageTextArea;
}
public void printRawMessage(String rawMessage) {
getMessageTextArea().append(rawMessage);
getMessageTextArea().setCaretPosition(getMessageTextArea().getText().length());
}
}
布局的东西基本上发生在initComponents()
.
要查看问题:
- 启动应用程序(我使用 miglayout-4.0-swing.jar)。
- 稍等一下(不要调整窗口大小),直到有足够的消息在状态文本区域中创建滚动条。
- 现在这就是我想要的。
JTextArea
一直到 JFrame 的底部,并在必要时滚动。 - 现在调整窗口大小。如您所见,一切都变得一团糟。如果窗口最大化,它只会很好。
这是两个屏幕截图。第一个是我想要的样子: 第二个是调整大小后:
我的问题:有人能告诉我,我如何在调整大小之前保持布局不变?我想一直JTextArea
走到窗口的底部。如果有必要,滚动条应该会出现。唯一的办法是,如果窗口太小(因为配置面板有固定的高度),状态面板可以低于窗口底部。
我希望我说清楚了。如果没有,请询问。;)
编辑:如果您删除顶部 JScrollPanel(包含所有组件的那个),您可以看到我想要的行为。只是改变
JScrollPane contentScrollPane = new JScrollPane(mainPanel);
contentScrollPane.setBorder(BorderFactory.createEmptyBorder());
setContentPane(contentScrollPane);
至
setContentPane(mainPanel);
看看我的意思。不幸的是,如果窗口很小,这样我就会松开滚动条。