java - Swing:GridBagLayout动态复选框位置

标签 java swing jpanel gridbaglayout

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

enter image description here

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

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

    }

最佳答案

通过将 gbc.weightx 设置为 0,您可以限制组件在水平方向上聚集在一起。增加该值。

至于高度问题,我会通过使用 JPanel 将当前的 GridBagLayout 包装在另一个使用 BorderLayout 的 GridBagLayout 中,并使用 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());
    }
}

关于java - Swing:GridBagLayout动态复选框位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44343972/

相关文章:

java - 异步 Java RMI

java - 如何从 Guice 中按类获取对象列表?

java - 将 jtoolbar 从一个 jpanel 转移到另一个 jpanel

java - 如何结合 JLabel 和 JFrame?

java - java小程序中的淡入淡出效果

Java zip 文件已创建但无法打开,提示文件意外结束

java - JTabbedPane 选项卡高度与 nimbus

java - 减少 JPanel 之间的间隙

Java JPanel 绘制缩放

java - JFrame 的内容转换为 JPanel