Swing:GridBagLayout动态复选框位置

时间:2017-06-03 12:33:44

标签: java swing jpanel gridbaglayout

我想将所有复选框和标签对齐到左侧,并且还要删除两个复选框之间的垂直空间,如图所示。

enter image description here

这是我到目前为止所做的。 要将其设置在左上角,我已将属性设置为GridBagConstraints.NORTHWEST。但它没有用。 另外,对于两个复选框之间的空间,我设置了Insets但它不起作用。 有什么我理解错了吗?请帮帮我。谢谢。

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));
    }

这是JFrame代码:

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"));

    }

1 个答案:

答案 0 :(得分:1)

通过使你的gbc.weightx为0,你可以限制组件在水平方向上聚集在一起。增加这个值。

至于高度问题,我通过使用JPanel将当前GridBagLayout包装在另一个使用BorderLayout,并使用JPanel将GridBagLayout添加到其BorderLayout.PAGE_START位置,然后将包装器JPanel添加到GUI。

我的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);
    }

}

我还使用了两个JLabel,一个用于图标,一个用于文本,因此它们可以正确间隔,我必须在这两个标签上使用weightx来使它看起来很好。有关详细信息,请参阅上面的MCVE。

编辑:我不得不怀疑JTable是否是您真正想要使用的 侧面问题:没有理由一遍又一遍地继续阅读同一张图片。一次读取并将其放入变量中,然后根据需要重新使用该变量。

玩一些JTable代码......

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());
    }
}