使用Jlabel中的自定义子类时,GridBagLayout会堆叠标签

时间:2016-07-25 11:30:33

标签: java swing awt jlabel gridbaglayout

我正在用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);
            }
        }
    }
}

问题出在哪里?

2 个答案:

答案 0 :(得分:3)

您的代码中有许多问题需要解决,但您的问题源于3件事:

  1. 自定义标签中的方法定义:

    public class TileLabel extends JLabel {
    
        // @Override !!!!
        public int getX() {
            return x;
        }
    
        // @Override !!!!
        public int getY() {
            return y;
        }
    }
    

    您要覆盖JComponent getX()getY(),它们负责返回其坐标。这完全搞砸了布局。

    小心你的paint方法,超类中存在一个同名的方法,尽管在这种情况下你保存了,因为参数不同。

  2. 您的循环错误:gui.paint(tile, x, x)应为gui.paint(tile, x, y)

  3. 调用方法的顺序错误。首先,创建框架并显示它,然后通过添加带有标签的面板来更改其内容,然后更改标签中的文本。你应该这样做。

  4. 我的建议:

    • 让您的paint方法成为TileLabel课程的成员。这更有意义。
    • 在创建标签期间设置图标,除非它们未知。如果不能,您可能需要重新计算空间要求。
    • 切勿使布局取决于屏幕尺寸或分辨率。它构成了一个脆弱的GUI(如评论中所述)。使用pack()作为框架来计算正确的尺寸。

答案 1 :(得分:1)

Override

您不小心覆盖了JComponent#getX() and JComponent#getY()。此方法返回的值与布局可在内部设置的值一致(通过调用setBounds左右)。这会弄乱布局。

(不可否认,我没有真正检查这是否是原因,但很可能是,而且一般来说这是一个问题!)