簡體   English   中英

GridBagLayout在使用Jlabel中的自定義子類時會堆疊標簽

[英]GridBagLayout stacks labels when using custom subclass from Jlabel

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

問題出在哪兒?

您的代碼中有很多要解決的問題,但是您的問題源自三件事:

  1. 您的自定義標簽中的方法定義:

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

    您將重寫JComponentgetX()getY() ,它們負責返回它們的坐標。 這完全弄亂了布局。

    請注意您的paint方法,在同一個類中存在一個具有相同名稱的方法,盡管在這種情況下您會被保存,因為參數是不同的。

  2. 您在循環中gui.paint(tile, x, x)錯別字: gui.paint(tile, x, x)應該是gui.paint(tile, x, y)

  3. 您調用方法的順序是錯誤的。 首先,創建框架並顯示它,然后通過添加帶有標簽的面板來更改其內容,然后更改標簽中的文本。 您應該以其他方式執行此操作。

我的建議:

  • 使您的paint方法成為TileLabel類的成員。 這更有意義。
  • 除非不知道,否則在創建標簽期間設置圖標。 如果不能,則可能需要重新計算空間需求。
  • 切勿使布局取決於屏幕的大小或其分辨率。 它導致脆弱的GUI(如注釋中所述)。 對框架使用pack()來計算正確的大小。

覆寫

您不小心覆蓋了JComponent#getX()JComponent#getY() 此方法返回的值是與該布局可以內部設置(通過調用的值一致setBounds左右)。 這弄亂了布局。

(誠​​然,我並沒有真正檢查這是否是原因,但很可能是這樣,而且通常是個問題!)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM