我正在用Swing编写GUI。我正在使用GridBagLayout
在网格中显示多个JLabels
(基本上像棋盘)。只要我使用源自JLabel
而不是JLabel
的自制标签类,GridBagLayout
就会堆叠JPanel
左上角的每个标签。
我的子类TileLabel
不正确或者我没有以正确的方式使用布局和约束。我想最后一个因为我看不出在这样一个最小的子类中会出现什么问题。
这是使用JLabel
看起来的样子(L代表标签):
(MenuBar)
L L L L L L L L L
L L L L L L L L L
L L L L L L L L L
这是使用TileLabel
看起来的样子(S表示堆叠的所有标签):
(MenuBar)
S
这是我在JLabel中的简单子类:
import javax.swing.JLabel;
public class TileLabel extends JLabel {
private static final long serialVersionUID = 6718776819945522562L;
private int x;
private int y;
public TileLabel(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
这是GUI类。我标记了三条线,我使用自定义标签导致布局问题。
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainGUI extends JPanel {
private static final long serialVersionUID = -8750891542665009043L;
private JFrame frame;
private MainMenuBar menuBar;
private TileLabel[][] labelGrid; // <-- LINE 1
private GridBagConstraints constraints;
private int gridWidth;
private int gridHeight;
// Basic constructor.
public MainGUI(int frameWidth, int frameHeight) {
super(new GridBagLayout());
constraints = new GridBagConstraints();
buildFrame(frameWidth, frameHeight);
buildLabelGrid(frameWidth, frameHeight);
}
// Builds the frame.
private void buildFrame(int frameWidth, int frameHeight) {
menuBar = new MainMenuBar();
frame = new JFrame("Carcasonne");
frame.getContentPane().add(this);
frame.setJMenuBar(menuBar);
frame.setResizable(false);
frame.setVisible(true);
frame.setSize(frameWidth, frameHeight);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(new Color(165, 200, 245));
}
// Creates the grid of labels.
private void buildLabelGrid(int frameWidth, int frameHeight) {
gridWidth = frameWidth / 100;
gridHeight = frameHeight / 100;
labelGrid = new TileLabel[gridWidth][gridHeight]; // <-- LINE 2
for (int x = 0; x < gridWidth; x++) {
for (int y = 0; y < gridHeight; y++) {
labelGrid[x][y] = new TileLabel(x, y); // <-- LINE 3
constraints.gridx = x;
constraints.gridy = y;
add(labelGrid[x][y], constraints); // add label with constraints
}
}
}
// sets the icon of a specific label
public void paint(Tile tile, int x, int y) {
if (x >= 0 && x < gridWidth && y >= 0 && y < gridHeight) {
labelGrid[x][y].setIcon(tile.getImage());
} else {
throw new IllegalArgumentException("Invalid label grid position (" + x + ", " + y + ")");
}
}
// Just to test this GUI:
public static void main(String[] args) {
MainGUI gui = new MainGUI(1280, 768);
Tile tile = TileFactory.createTile(TileType.Road);
for (int x = 0; x < 12; x++) {
for (int y = 0; y < 7; y++) {
gui.paint(tile, x, x);
}
}
}
}
问题出在哪里?
答案 0 :(得分:3)
您的代码中有许多问题需要解决,但您的问题源于3件事:
自定义标签中的方法定义:
public class TileLabel extends JLabel {
// @Override !!!!
public int getX() {
return x;
}
// @Override !!!!
public int getY() {
return y;
}
}
您要覆盖JComponent
getX()
和getY()
,它们负责返回其坐标。这完全搞砸了布局。
小心你的paint
方法,超类中存在一个同名的方法,尽管在这种情况下你保存了,因为参数不同。
您的循环错误:gui.paint(tile, x, x)
应为gui.paint(tile, x, y)
。
调用方法的顺序错误。首先,创建框架并显示它,然后通过添加带有标签的面板来更改其内容,然后更改标签中的文本。你应该这样做。
我的建议:
paint
方法成为TileLabel
课程的成员。这更有意义。 pack()
作为框架来计算正确的尺寸。答案 1 :(得分:1)
您不小心覆盖了JComponent#getX()
and JComponent#getY()
。此方法返回的值不与布局可在内部设置的值一致(通过调用setBounds
左右)。这会弄乱布局。
(不可否认,我没有真正检查这是否是原因,但很可能是,而且一般来说这是一个问题!)