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

时间:2014-08-30 22:35:37

标签: java swing layout-manager grouplayout

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

我有两个类扩展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);
            }
        }
    }
}

MazeSolverInterface:

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

1 个答案:

答案 0 :(得分:2)

确实为GUI工具创建了

GroupLayout,但它可以 手动使用没有问题。从内置的经理那里就是一个 我建议使用。

我稍微修改了你的例子:

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 永远,并与GroupLayoutMigLayout经理完全建立解决方案。 (GridLayout不可移植,因为它以像素为单位设置边距。但事实并非如此 因为我们选择的固定空间在各种屏幕分辨率上都不正确,所以最佳。 在较小的屏幕上什么是好的,在较大的屏幕上是不行的。一般来说,我们应该避免 以像素为单位设置尺寸这也适用于您重写的getPreferredSize()方法。)

Maze