Reputation: 93
I am creating something like inspector panel for my program, so I can easily change some variables at runtime.
When you run the code bellow, you should see something like this: inspector screenshot
There are several things that bothers me and I still cannot make them to work properly.
inspector.finish()
but the solution seems kinda hacky to me. It works by adding empty JPanel as last item on the panel, acting as some kind of vertical glue to expand the lower area and push the components up. I don't like this, because with this solution I no longer can add more items to the inspector later at runtime.Maybe I am using the wrong layout manager, but I don't know which other one to choose. I was thinking about simple grid layout, but this does not allow me to do things like having some rows with one item and others with multiple items in such a way that they will always use the whole width "capacity" of the row.
example code:
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);
}
}
}
Upvotes: 0
Views: 117
Reputation: 1246
The Reason that you can't scroll up or down is because you are setting the preferred size of sp
to 200x0. You need to remove this line.
p.setPreferredSize(new Dimension(200, 0));
As for the issue with everything being centered instead of at the top. I would prefer to leave p
with the default FlowLayout
and give each "section" it's own panel, and the make that panel a GridBagLayout
. By doing this you probably will not need addSeparator()
anymore.
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);
}
}
}
Upvotes: 1