Java Swing API - GroupLayout 未正确调整所有组件 JPanel 的大小

标签 java swing layout-manager grouplayout

我昨天才开始使用 Java Swing,所以如果这不是一个有效的问题,请原谅我。我一直在尝试创建一个带有网格和面板的简单用户界面,允许用户指定网格尺寸的大小。

我有两个扩展 JPanel 的类:GridSizePanelGridBoxPanelGridSizePanel 指定设计允许用户更改尺寸的面板时涉及的标题、边框、标签和字段。 GridBoxPanel 显示实际网格(采用 here )。 GridSizePanel 使用 GroupLayout 作为其 LayoutManager,GridBoxPanel 使用 GridBagLayout。编排这些子面板的父 JFrame 类 (MazeSolverInterface) 使用 GroupLayout 作为 LayoutManager。

问题是,如果我只将 GridSizePanel 添加到 MazeSolverInterface 的 GroupLayout 中,当我手动调整窗口大小时,我可以看到 GridSizePanel 自动调整大小。都好。

但是,当我将 GridBoxPanel 添加到 MazeSolverInterface 时,现在当我手动调整窗口大小时,似乎只有 GridBoxPanel 会调整大小。 GridSizePanel 根本不改变尺寸!

这是我到目前为止的代码:

GridSizePanel:

public class GridSizePanel extends JPanel implements PropertyChangeListener {


    public GridSizePanel() throws ParseException {

        // set the border properties
        TitledBorder title = BorderFactory.createTitledBorder("Grid Size");
        title.setTitleColor(Color.BLACK);
        title.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED,
                Color.DARK_GRAY, Color.GRAY));
        this.setBorder(title);

        // wire up the group layout and panel to
        // each other
        GroupLayout gl = new GroupLayout(this);
        this.setLayout(gl);

        // Turn on automatically adding gaps between components
        gl.setAutoCreateGaps(true);

        // Turn on automatically creating gaps between components that touch
        // the edge of the container and the container.
        gl.setAutoCreateContainerGaps(true);

        JLabel numRowsLabel = new JLabel("rows");
        JLabel numColsLabel = new JLabel("columns");

        MaskFormatter textMask = new MaskFormatter("##");
        textMask.setPlaceholder("16");
        JFormattedTextField rowsText = new JFormattedTextField(textMask);
        JFormattedTextField colsText = new JFormattedTextField(textMask);

        // configure the text fields
        rowsText.setColumns(50);
        colsText.setColumns(50);
        rowsText.addPropertyChangeListener("value", this);
        colsText.addPropertyChangeListener("value", this);

        GroupLayout.SequentialGroup horGroup = gl.createSequentialGroup();
        horGroup.addGroup(gl.createParallelGroup().addComponent(numRowsLabel).addComponent(numColsLabel))
                .addGroup(gl.createParallelGroup().addComponent(rowsText).addComponent(colsText));
        gl.setHorizontalGroup(horGroup);

        GroupLayout.SequentialGroup verGroup = gl.createSequentialGroup();
        verGroup.addGroup(gl.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(numRowsLabel).addComponent(rowsText))
                .addGroup(gl.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(numColsLabel).addComponent(colsText));
        gl.setVerticalGroup(verGroup);
    }

    //public GridSize getSize() {
    //    return new GridSize()
    //}

    @Override
    public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
        // TODO: fill this with logic to relay grid dimensions to the model
    }
}

GridBoxPanel:

public class GridBoxPanel extends JPanel {

    public GridBoxPanel() {
        setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();
        for (int row = 0; row < 32; row++) {
            for (int col = 0; col < 32; col++) {
                gbc.gridx = col;
                gbc.gridy = row;

                GridCell gridCell = new GridCell();
                Border border = null;
                if (row < 4) {
                    if (col < 4) {
                        border = new MatteBorder(1, 1, 0, 0, Color.GRAY);
                    } else {
                        border = new MatteBorder(1, 1, 0, 1, Color.GRAY);
                    }
                } else {
                    if (col < 4) {
                        border = new MatteBorder(1, 1, 1, 0, Color.GRAY);
                    } else {
                        border = new MatteBorder(1, 1, 1, 1, Color.GRAY);
                    }
                }
                gridCell.setBorder(border);
                add(gridCell, gbc);
            }
        }
    }
}

迷宫求解器界面:

public class MazeSolverInterface extends JFrame {

    public MazeSolverInterface(String[] args) throws ParseException {
        checkArgs(args);
        initMaze(args);
    }

    public void initMaze(String[] args) throws ParseException {
        Container pane = getContentPane();
        GroupLayout gl = new GroupLayout(pane);
        pane.setLayout(gl);

        gl.setAutoCreateContainerGaps(true);

        // create required panels to integrate
        GridSizePanel gridSizeComponent = new GridSizePanel();
        GridBoxPanel gridDrawComponent = new GridBoxPanel();

        gl.setHorizontalGroup(gl.createSequentialGroup().addComponent(gridDrawComponent).addGap(50).addComponent(gridSizeComponent));
        gl.setVerticalGroup(gl.createParallelGroup().addComponent(gridDrawComponent).addGap(50).addComponent(gridSizeComponent));
        pack();

        setTitle("v0.0.1");
        setSize(700, 700);  // TODO: change to something configurable
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public void checkArgs(String[] args) {
        // TODO: fill with logic to check valid arguments (initial window dimensions)
    }
}

主要:

public class Main {

    public static void main(final String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MazeSolverInterface ex = null;
                try {
                    ex = new MazeSolverInterface(args);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                ex.setVisible(true);
            }
        });
    }
}

以下是将 GridBoxLabel 添加到 MazeSolverInterface 之前的 UI 外观:

enter image description here

...并将 GridBoxLabel 添加到 MazeSolverInterface 后:

enter image description here

感谢任何/所有帮助。谢谢!

编辑: 正如您在上面看到的,GridBoxPanel 使用 GridCell 类。我忘了将其添加到这篇文章中,所以就在这里。希望这有帮助!

网格单元:

public class GridCell extends JPanel {

    private Color defaultBackground;

    public GridCell() {
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                defaultBackground = getBackground();
                setBackground(Color.BLUE);
            }

            @Override
            public void mouseExited(MouseEvent e) {
                setBackground(defaultBackground);
            }
        });
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(50, 50);
    }
}

最佳答案

GroupLayout 确实是为 GUI 工具创建的,但是,它可以 手动使用没有问题。从内置管理器来看,它是一个 我推荐使用。

我对你的例子做了一些修改:

MazeSolverInterface.java

import java.awt.Container;
import java.text.ParseException;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.Alignment.BASELINE;
import static javax.swing.GroupLayout.Alignment.TRAILING;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.text.MaskFormatter;

public class MazeSolverInterface extends JFrame {

    public MazeSolverInterface(String[] args) throws ParseException {

        initMaze(args);
    }

    private void initMaze(String[] args) throws ParseException {

        Container pane = getContentPane();
        GroupLayout gl = new GroupLayout(pane);
        pane.setLayout(gl);

        gl.setAutoCreateContainerGaps(true);

        gl.setAutoCreateGaps(true);

        JLabel numRowsLabel = new JLabel("Rows:");
        JLabel numColsLabel = new JLabel("Columns:");

        MaskFormatter textMask = new MaskFormatter("##");
        //textMask.setPlaceholder("16");
        JFormattedTextField rowsText = new JFormattedTextField(textMask);
        JFormattedTextField colsText = new JFormattedTextField(textMask);

        rowsText.setColumns(20);
        colsText.setColumns(20);

        GridBoxPanel gridDrawComponent = new GridBoxPanel();

        gl.setHorizontalGroup(gl.createParallelGroup()
                .addGroup(gl.createSequentialGroup()
                        .addGroup(gl.createParallelGroup(TRAILING)
                                .addComponent(numRowsLabel)
                                .addComponent(numColsLabel))
                        .addGroup(gl.createParallelGroup()
                                .addComponent(rowsText)
                                .addComponent(colsText)))
                .addComponent(gridDrawComponent));

        gl.setVerticalGroup(gl.createSequentialGroup()
                .addGroup(gl.createParallelGroup(BASELINE)
                        .addComponent(numRowsLabel)
                        .addComponent(rowsText))
                .addGroup(gl.createParallelGroup(BASELINE)
                        .addComponent(numColsLabel)
                        .addComponent(colsText))
                .addComponent(gridDrawComponent));

        pack();

        setTitle("v0.0.1");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
}

我已经摆脱了 GridSizePanel 并将代码移至 MazeSolverInterface 中。从设计的角度来看,如果没有其他具体的说明,则不需要标题面板。 面板。标签右对齐。当文本字段和迷宫对象增大或缩小时 窗口大小已调整。

setSize() 方法已被删除,因为最好使用 pack() 方法。 您可以使用其中之一,但不能同时使用两者。

GridBoxPanel.java

import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;

public class GridBoxPanel extends JPanel {

    public GridBoxPanel() {
        setLayout(new GridLayout(32, 32, 1, 1));

        for (int row = 0; row < 32; row++) {
            for (int col = 0; col < 32; col++) {

                GridCell gridCell = new GridCell();
                Border border = null;
                if (row < 4) {
                    if (col < 4) {
                        border = new MatteBorder(1, 1, 0, 0, Color.GRAY);
                    } else {
                        border = new MatteBorder(1, 1, 0, 1, Color.GRAY);
                    }
                } else {
                    if (col < 4) {
                        border = new MatteBorder(1, 1, 1, 0, Color.GRAY);
                    } else {
                        border = new MatteBorder(1, 1, 1, 1, Color.GRAY);
                    }
                }
                gridCell.setBorder(border);
                add(gridCell);
            }
        }
    }
}

这里我使用了 GridLayout 管理器而不是 GridBagLayout。 (这也许是 只有我发现 GridLayout 有用的第三个示例。) 我进行了此修改以使事情变得更容易,但我个人不会使用 GridLayout 完全使用 GroupLayout 或 MigLayout 管理器创建解决方案。 (GridLayout 不可移植,因为它以像素为单位设置边距。这不是 最佳选择,因为我们选择的固定空间在所有屏幕分辨率上并不正确。 在小屏幕上可以的东西,在大屏幕上就不行了。一般来说,我们应该避免 以像素为单位设置尺寸。这也适用于您重写的 getPreferredSize() 方法。)

Maze

关于Java Swing API - GroupLayout 未正确调整所有组件 JPanel 的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25587318/

相关文章:

java - 在多个 JPanel 上使用 JPanel

java - 将 GridLayout 添加到 GroupLayout

java - JSF 验证错误 h :selectOneMenu but for only one item

java - 自定义比较器未正确排序

java - 如何在eclipse中配置javadb?

java - 为什么 java newInstance 卡在 getDeclaredConstructors0 处?

java - 使用 SourceDataLine 时帧速率不稳定

java - JComponent InputMap 神秘地被删除

java - JFrame : setDefaultCloseOperation has no effect

java - 在任何屏幕分辨率下定位图像