我昨天才开始使用 Java Swing,所以如果这不是一个有效的问题,请原谅我。我一直在尝试创建一个带有网格和面板的简单用户界面,允许用户指定网格尺寸的大小。
我有两个扩展 JPanel 的类:GridSizePanel
和 GridBoxPanel
。 GridSizePanel
指定设计允许用户更改尺寸的面板时涉及的标题、边框、标签和字段。 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 外观:
...并将 GridBoxLabel 添加到 MazeSolverInterface 后:
感谢任何/所有帮助。谢谢!
编辑:
正如您在上面看到的,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()
方法。)
关于Java Swing API - GroupLayout 未正确调整所有组件 JPanel 的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25587318/