I am trying to center components using a GridBagLayout
in the same manner that a Box
centers components when you use Box.createVerticalGlue()
. I initially did use a vertical Box:
Box box = Box.createVerticalBox();
box.add(Box.createVerticalGlue());
box.add(add);
box.add(remove);
box.add(edit);
box.add(Box.createVerticalGlue());
JPanel internalPanel = new JPanel(new BorderLayout());
internalPanel.add(keywordsScrollPane, BorderLayout.CENTER);
internalPanel.add(box, BorderLayout.EAST);
But as you can see, it looks sloppy because my buttons are different sizes:
I decided to switch to GridBagLayout
so I can utilize GridBagConstraints.fill
. This approach fixes my button width issue, but I cannot figure out how to vertically center the buttons. I changed the grid size and placed the buttons in the middle three rows, but the buttons were still appearing at the top of the panel. I tried making use of GridBagConstraints.anchor
and GridBagConstraints.weighty
as well. The latter almost worked, but there are very large margins between the buttons:
I am looking for the buttons to be grouped together as they were in my Box approach. How can I achieve this with a GridBadLayout?
I am using a class I created called ConstraintsBuilder
which works exactly as you would expect. It's for creating GridBagContraints with nice one-liners. Here is all the (relevant) code for your viewing pleasure:
public class KeywordsDialog extends JDialog implements ActionListener, ListSelectionListener {
private JList<String> keywords;
private JScrollPane keywordsScrollPane;
private JButton add;
private JButton remove;
private JButton edit;
private Set<String> keywordsList;
public KeywordsDialog(Window parent, Collection<String> keywordsList) {
super(parent);
this.keywordsList = keywordsList == null ? new HashSet<String>() : new HashSet<String>(keywordsList);
if (keywordsList != null && !keywordsList.isEmpty()) {
this.keywords = new JList<String>(toListModel(keywordsList));
} else {
this.keywords = new JList<String>(new DefaultListModel<String>());
}
this.keywordsScrollPane = new JScrollPane(keywords);
this.add = new JButton("Add");
this.remove = new JButton("Remove");
this.edit = new JButton("Edit");
this.edit.setEnabled(false);
this.add.setEnabled(false);
ConstraintsBuilder builder = LayoutUtils.gridBagConstraintsBuilder();
JPanel internalPanel = new JPanel(new GridBagLayout());
internalPanel.add(this.keywordsScrollPane, builder.gridX(0).gridY(0).gridHeight(3).margins(0, 0, 0, 5)
.fill(GridBagConstraints.BOTH).weightX(1D).weightY(1D).build());
internalPanel.add(this.add,
builder.reset().gridX(1).gridY(0).fill(GridBagConstraints.HORIZONTAL).weightX(1D).weightY(1D).build());
internalPanel.add(this.remove,
builder.reset().gridX(1).gridY(1).fill(GridBagConstraints.HORIZONTAL).weightX(1D).weightY(1D).build());
internalPanel.add(this.edit,
builder.reset().gridX(1).gridY(2).fill(GridBagConstraints.HORIZONTAL).weightX(1D).weightY(1D).build());
this.keywords.setBorder(BorderFactory.createTitledBorder("Keywords"));
internalPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
this.setLayout(new BorderLayout());
this.add(internalPanel, BorderLayout.CENTER);
Dimension screen = GuiHelper.getScreenSize(parent);
this.setSize((int) (screen.getWidth() / 4), (int) (screen.getHeight() / 3));
this.setLocationRelativeTo(parent);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
// ...
}
I would make the GUI simpler. Put the three buttons into a JPanel that uses a GridLayout, one declared to use 1 column and variable number of rows, one with a desired spacing between buttons, here, 5 pixels: JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 5, 5));
and then put that JPanel into the center of a another JPanel, and GridBagLayout without constraints works well for this:
JPanel sidePanel = new JPanel(new GridBagLayout());
sidePanel.add(buttonPanel);
and put that JPanel into the right side of a border layout using JPanel. For example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FooSwing01 extends JPanel {
public FooSwing01() {
JTextArea textArea = new JTextArea(20, 50);
JScrollPane scrollPane = new JScrollPane(textArea);
JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 5, 5));
int maxButtons = 3;
for (int i = 0; i < maxButtons; i++) {
buttonPanel.add(new JButton("Button " + (i + 1)));
}
JPanel sidePanel = new JPanel(new GridBagLayout());
sidePanel.add(buttonPanel);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(scrollPane);
add(sidePanel, BorderLayout.LINE_END);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("GUI");
frame.add(new FooSwing01());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}