I want to align all check boxes and label to the left and also wan to remove vertical space between two check boxes as shown in image.
Here is what i have done so far now.
For setting it on top-left, i have set property to GridBagConstraints.NORTHWEST
. But it is not working.
Also for space between two checkboxes, I have set Insets but it aint working.
Is there anything i am understanding wrong? Please help me out. Thank you.
public MultipleCheckBoxesPanel(String... options) {
checkBoxes = new ArrayList<>();
setLayout(new BorderLayout());
JPanel header = new JPanel(new FlowLayout(FlowLayout.LEFT, 1, 1));
all = new JCheckBox("RigFiles (Select All)");
all.addActionListener((ActionEvent e) -> {
for (JCheckBox cb : checkBoxes) {
cb.setSelected(all.isSelected());
}
});
header.add(all);
add(header, BorderLayout.NORTH);
JPanel content = new ScrollablePane(new GridBagLayout());
content.setBackground(Color.WHITE);
if (options.length > 0) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(4, 4, 4, 4);
gbc.weightx = 0;
gbc.weighty = 1;
gbc.gridy = 0;
for (int index = 0; index < options.length; index++) {
final ImageIcon image = new ImageIcon(getClass().getResource("/images/folder.png"));
JCheckBox cb = new JCheckBox();
cb.setOpaque(false);
checkBoxes.add(cb);
content.add(cb, gbc);
JLabel label = new JLabel(options[index], image, 0);
content.add(label, gbc);
gbc.gridy++;
}
}
add(new JScrollPane(content));
}
Here is JFrame code:
public FolderSpecificSyncFrame() {
setTitle("Select Folders to synch from web");
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
add(new MultipleCheckBoxesPanel(new String[]{"Bananas", "Oranages", "Apples", "Pears"}));
pack();
getDim();
setSize(250, 300);
setLocation(this.width, this.height);
setResizable(false);
setFocusable(true);
setIconImage(new Global().createImage("/images/icon_large.png", "tray icon"));
}
By making your gbc.weightx 0, you're constraining the components to crowd together in the horizontal direction. Increase this value.
As for the height issue, I'd solve that by wrapping the current GridBagLayout using JPanel in another that uses BorderLayout, and adding the GridBagLayout using JPanel to its BorderLayout.PAGE_START position, and than add the wrapper JPanel to the GUI.
My MCVE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.*;
import java.io.File;
import java.util.ArrayList;
import javax.swing.*;
@SuppressWarnings("serial")
public class FolderSpecificSyncFrame extends JFrame {
public FolderSpecificSyncFrame() {
setTitle("Select Folders to synch from web");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new MultipleCheckBoxesPanel(
new String[] { "Bananas", "Oranages", "Apples", "Pears", "Bananas", "Oranages",
"Apples", "Pears", "Bananas", "Oranages", "Apples", "Pears", "Bananas",
"Oranages", "Apples", "Pears", "Bananas", "Oranages", "Apples", "Pears" }));
pack();
setSize(250, 300);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new FolderSpecificSyncFrame().setVisible(true);
});
}
}
@SuppressWarnings("serial")
class MultipleCheckBoxesPanel extends JPanel {
private ArrayList<JCheckBox> checkBoxes;
private JCheckBox all;
public MultipleCheckBoxesPanel(String... options) {
checkBoxes = new ArrayList<>();
setLayout(new BorderLayout());
JPanel header = new JPanel(new FlowLayout(FlowLayout.LEFT, 1, 1));
all = new JCheckBox("RigFiles (Select All)");
all.addActionListener((ActionEvent e) -> {
for (JCheckBox cb : checkBoxes) {
cb.setSelected(all.isSelected());
}
});
header.add(all);
add(header, BorderLayout.NORTH);
JPanel content = new ScrollablePane(new GridBagLayout());
content.setBackground(Color.WHITE);
javax.swing.JFileChooser fc = new javax.swing.JFileChooser();
Icon image = fc.getUI().getFileView(fc).getIcon(new File("."));
if (options.length > 0) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(4, 4, 4, 4);
gbc.weightx = 1.0; // !!
gbc.weighty = 1.0;
gbc.gridy = 0;
gbc.gridx = 0;
gbc.fill = GridBagConstraints.HORIZONTAL; // !!
for (int index = 0; index < options.length; index++) {
JCheckBox cb = new JCheckBox();
cb.setOpaque(false);
checkBoxes.add(cb);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 0;
content.add(cb, gbc);
// JLabel label = new JLabel(options[index], image, 0);
JLabel label1 = new JLabel(image);
gbc.anchor = GridBagConstraints.CENTER;
gbc.weightx = 0;
gbc.gridx++;
content.add(label1, gbc);
gbc.weightx = 1.0;
gbc.gridx++;
JLabel label2 = new JLabel(options[index]);
content.add(label2, gbc);
gbc.gridy++;
}
}
JPanel wrapperPanel = new JPanel(new BorderLayout());
wrapperPanel.setBackground(Color.WHITE);
wrapperPanel.add(content, BorderLayout.PAGE_START);
add(new JScrollPane(wrapperPanel));
}
}
@SuppressWarnings("serial")
class ScrollablePane extends JPanel {
public ScrollablePane(GridBagLayout layout) {
super(layout);
}
}
I also used two JLabels, one for the icon and one for the text, so that they'll be spaced correctly, and I had to play with the weightx on both of these labels to get it looking good. Please see my MCVE above for the details.
Edit: I do have to wonder if a JTable is what you really want to use.
Side issue: no reason to keep reading in the same image over and over. Read it in once and put it in a variable, and then re-use the variable as needed.
Playing with some JTable code....
import java.awt.Dialog.ModalityType;
import java.awt.event.ItemEvent;
import java.io.File;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
@SuppressWarnings("serial")
public class FolderTableExample extends JPanel {
private static final int PREF_W = 250;
private static final int PREF_H = 300;
private static final int[] COL_WIDTHS = {45, 45, 100};
private MyTableModel myTableModel = new MyTableModel();
private JTable table = new JTable(myTableModel);
private JCheckBox all = new JCheckBox("Select All");
public FolderTableExample(String... options) {
super(new BorderLayout());
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
topPanel.add(all);
all.addItemListener(itemEvent -> {
boolean selection = itemEvent.getStateChange() == ItemEvent.SELECTED;
for (int i = 0; i < myTableModel.getRowCount(); i++) {
myTableModel.setValueAt(selection, i, 0);
}
});
table.setTableHeader(null);
javax.swing.JFileChooser fc = new javax.swing.JFileChooser();
Icon icon = fc.getUI().getFileView(fc).getIcon(new File("."));
for (String option : options) {
Object[] row = {Boolean.FALSE, icon, option};
myTableModel.addRow(row);
}
table.setRowHeight(25);
table.setFont(table.getFont().deriveFont(Font.BOLD));
table.setShowGrid(false);
TableColumnModel columnModel = table.getColumnModel();
for (int i = 0; i < COL_WIDTHS.length; i++) {
columnModel.getColumn(i).setMaxWidth(COL_WIDTHS[i]);
}
JPanel wrapperPanel = new JPanel(new BorderLayout());
wrapperPanel.add(table, BorderLayout.PAGE_START);
add(topPanel, BorderLayout.PAGE_START);
add(new JScrollPane(wrapperPanel));
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyTableModel extends DefaultTableModel {
public MyTableModel() {
super(new Object[] { "", "", "" }, 0);
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return Boolean.class;
case 1:
return Icon.class;
default:
return super.getColumnClass(columnIndex);
}
}
}
private static void createAndShowGui() {
String[] array = new String[] { "Bananas", "Oranages", "Apples", "Pears", "Bananas",
"Oranages", "Apples", "Pears", "Bananas", "Oranages", "Apples", "Pears", "Bananas",
"Oranages", "Apples", "Pears", "Bananas", "Oranages", "Apples", "Pears" };
FolderTableExample mainPanel = new FolderTableExample(array);
JDialog dialog = new JDialog((JFrame) null, "Example", ModalityType.MODELESS);
dialog.getContentPane().add(mainPanel);
dialog.setResizable(false);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}