我正在为我的程序创建类似检查器面板的东西,因此我可以在运行时轻松更改一些变量。
当您运行下面的代码时,您应该看到如下内容: inspector screenshot
有几件事困扰着我,但我仍然无法使它们正常工作。
- 项目与中心垂直对齐...我尝试将锚定到北方,但它保持不变。在下面的示例代码中,注释掉一行可以解决此问题:
inspector.finish()
,但该解决方案对我来说似乎有点老套。它的工作原理是添加空的 JPanel 作为面板上的最后一项,充当某种垂直粘合剂来扩展下部区域并将组件向上推。我不喜欢这个,因为使用这个解决方案,我无法再在运行时向检查器添加更多项目。 - 如果您向检查器添加更多项目(您可以通过更改用一些测试数据填充检查器的 n 变量来做到这一点),滚动条将不会显示,并且所有较低的项目都会显示即使它全部包裹在 JScrollPane 内,也超出了屏幕...我尝试了几种方法来解决此问题,但没有一个能正常工作。其中之一是将 JPanel 的 PreferredSize 设置为某些硬编码尺寸,但我不喜欢这样做,因为我不知道面板的确切大小。
- 当您按下一些微调器按钮,然后单击组合框(标题为“选择我”)时,选项将隐藏在下面的按钮后面。这看起来像是某种 z 排序问题。也许这是 swing 中的错误,不知道。
- 当您将窗口垂直调整为较小尺寸时,顶部的项目将开始缩小,而不是保持相同的尺寸。是否有任何选项可以将它们始终设置为恒定高度?
也许我使用了错误的布局管理器,但我不知道该选择哪一个。我正在考虑简单的网格布局,但这不允许我做一些事情,比如让一些行包含一个项目,其他行包含多个项目,这样它们将始终使用行的整个宽度“容量”。
示例代码:
import java.awt.*;
import javax.swing.*;
public class Test {
// Setup test scenario
public Test() {
// Create window
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
f.setSize(800, 600);
f.setTitle("Inspector");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// Create panel which will be used for the inspector
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(200, 0));
// Encapsulate it to the scroll panel so it can grow vertically
JScrollPane sp = new JScrollPane();
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
sp.setViewportView(p);
// Create the inspector inside panel p
Inspector inspector = new Inspector(p);
// Fill the inspector with some test data
int n = 3;
for (int i = 0; i < n; ++i) {
inspector.addTitle("Title");
inspector.addButton("push me");
inspector.addCheckBox("check me");
inspector.addSpinner("Spin me");
inspector.addTextField("Edit me", "here");
inspector.addComboBox("Choose one", new String[]{"A", "B", "C"});
inspector.addSeparator();
}
//inspector.finish();
// The inspector will be on the right side of the window
f.getContentPane().add(sp, BorderLayout.LINE_END);
// Show the window
f.setVisible(true);
}
// Main method
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Test();
}
});
}
// Inspector class itself
private class Inspector {
private final JPanel panel;
private final GridBagConstraints constraints;
private int itemsCount = 0;
public Inspector(JPanel p) {
panel = p;
panel.setLayout(new GridBagLayout());
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 0.5;
}
// Adds component which will span across whole row
private void addComponent(Component component) {
constraints.gridx = 0;
constraints.gridwidth = 2;
constraints.gridy = itemsCount;
panel.add(component, constraints);
itemsCount++;
}
// Adds descriptive label on the left and component on the right side of the row
private void addNamedComponent(String description, Component component) {
constraints.gridx = 0;
constraints.gridy = itemsCount;
constraints.gridwidth = 1;
panel.add(new JLabel(description), constraints);
constraints.gridx = 1;
constraints.gridy = itemsCount;
constraints.gridwidth = 1;
panel.add(component, constraints);
itemsCount++;
}
public void addSeparator() {
// (little hacky)
addComponent(new JPanel());
}
public void addTitle(String title) {
addComponent(new JLabel(title));
}
public void addButton(String actionName) {
addComponent(new Button(actionName));
}
public void addCheckBox(String description) {
addNamedComponent(description, new JCheckBox());
}
public void addSpinner(String description) {
addNamedComponent(description, new JSpinner());
}
public void addTextField(String description, String text) {
addNamedComponent(description, new JTextField(text));
}
public void addComboBox(String description, String[] options) {
JComboBox<String> comboBox = new JComboBox<>();
ComboBoxModel<String> model = new DefaultComboBoxModel<>(options);
comboBox.setModel(model);
addNamedComponent(description, comboBox);
}
public void finish() {
constraints.gridx = 0;
constraints.gridy = itemsCount;
constraints.gridwidth = 2;
constraints.weighty = 1.0;
panel.add(new JPanel(), constraints);
}
}
}
最佳答案
无法向上或向下滚动的原因是您将 sp
的首选大小设置为 200x0。您需要删除此行。
p.setPreferredSize(new Dimension(200, 0));
至于所有内容都集中而不是顶部的问题。我更愿意将 p
保留为默认的 FlowLayout
并为每个“部分”提供它自己的面板,并使该面板成为 GridBagLayout
。通过这样做,您可能不再需要 addSeparator()
了。
public class Test {
// Setup test scenario
public Test() {
// Create window
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
f.setSize(800, 600);
f.setTitle("Inspector");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// Create panel which will be used for the inspector
JPanel p = new JPanel();
// Encapsulate it to the scroll panel so it can grow vertically
JScrollPane sp = new JScrollPane();
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
sp.setViewportView(p);
// Create the inspector inside panel p
Inspector inspector = new Inspector(p);
// Fill the inspector with some test data
int n = 2;
for (int i = 0; i < n; ++i) {
inspector.addTitle("Title");
inspector.addButton("push me");
inspector.addCheckBox("check me");
inspector.addSpinner("Spin me");
inspector.addTextField("Edit me", "here");
inspector.addComboBox("Choose one", new String[]{"A", "B", "C"});
}
// The inspector will be on the right side of the window
f.getContentPane().add(sp, BorderLayout.LINE_END);
// Show the window
f.setVisible(true);
}
// Main method
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Test();
}
});
}
// Inspector class itself
private class Inspector {
private final JPanel panel;
private final GridBagConstraints constraints;
private int itemsCount = 0;
public Inspector(JPanel p) {
panel = new JPanel();
p.add(panel);
panel.setLayout(new GridBagLayout());
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1.0;
}
// Adds component which will span across whole row
private void addComponent(Component component) {
constraints.gridx = 0;
constraints.gridwidth = 2;
constraints.gridy = itemsCount;
panel.add(component, constraints);
itemsCount++;
}
// Adds descriptive label on the left and component on the right side of the row
private void addNamedComponent(String description, Component component) {
constraints.gridx = 0;
constraints.gridy = itemsCount;
constraints.gridwidth = 1;
panel.add(new JLabel(description), constraints);
constraints.gridx = 1;
constraints.gridy = itemsCount;
constraints.gridwidth = 1;
panel.add(component, constraints);
itemsCount++;
}
public void addSeparator() {
// (little hacky)
addComponent(new JPanel());
}
public void addTitle(String title) {
addComponent(new JLabel(title));
}
public void addButton(String actionName) {
addComponent(new Button(actionName));
}
public void addCheckBox(String description) {
addNamedComponent(description, new JCheckBox());
}
public void addSpinner(String description) {
addNamedComponent(description, new JSpinner());
}
public void addTextField(String description, String text) {
addNamedComponent(description, new JTextField(text));
}
public void addComboBox(String description, String[] options) {
JComboBox<String> comboBox = new JComboBox<>();
ComboBoxModel<String> model = new DefaultComboBoxModel<>(options);
comboBox.setModel(model);
addNamedComponent(description, comboBox);
}
public void finish() {
constraints.gridx = 0;
constraints.gridy = itemsCount;
constraints.gridwidth = 2;
constraints.weighty = 1.0;
panel.add(new JPanel(), constraints);
}
}
}
关于java - 创建类似 Inspector 的东西时 JScrollPane 和 GridBagLayout 出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38840148/