2016-07-25 82 views
1

我正在使用Swing編寫GUI。我使用GridBagLayout在網格中顯示多個JLabels(基本上像棋盤)。只要我使用JLabel而不是JLabel派生的自制標籤類,GridBagLayout將堆疊JPanel左上角的每個標籤。GridBagLayout在使用Jlabel的自定義子類時堆疊標籤

我的子類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); 
      } 
     } 
    } 
} 

問題在哪裏?

+1

*「基本上像一個棋盤」 *參見[製作一個健壯的,可調整大小的搖擺象棋GUI(http://stackoverflow.com/q/21142686/418556),用於對佈局的提示和用組分(例如每個網格廣場使用'JButton'而不是'JLabel')。 –

回答

1

Override

你不小心覆蓋JComponent#getX() and JComponent#getY()。此方法返回的值爲而不是與佈局可能在內部設置的值一致(通過調用setBounds左右)。這混亂了佈局。

(誠然,我真的不檢查這是否是原因,但很可能是,這是一般的問題!)

+0

這是問題所在。我用我的IDE生成了getters,並沒有意識到我覆蓋了這些方法。感謝你的幫助。 – ConveniencePatterns

3

有相當多的東西,以修正你的

  1. 你在你的自定義標籤的方法定義:

    public class TileLabel extends JLabel { 
    
        // @Override !!!! 
        public int getX() { 
         return x; 
        } 
    
        // @Override !!!! 
        public int getY() { 
         return y; 
        } 
    } 
    
    代碼,但你的問題,從3件事情起源

    您優先於JComponentgetX()getY(),它們負責返回其座標。這完全混淆了佈局。

    請注意您的paint方法,同名的方法存在於超類中,儘管由於參數不同而保存在本例中。

  2. 你在你的循環中有一個錯字:gui.paint(tile, x, x)應該是gui.paint(tile, x, y)

  3. 您調用方法的順序是錯誤的。首先,創建框架並將其顯示出來,然後通過添加帶有標籤的面板來更改其內容,然後更改標籤中的文本。你應該反過來這樣做。

我的建議:

  • 讓您paint方法制成的TileLabel類的成員。它更有意義。
  • 在創建標籤期間設置圖標,除非它們未知。如果你不能,你可能需要重新計算空間需求。
  • 不要讓您的佈局取決於屏幕的大小或其分辨率。它使得一個脆弱的GUI(如註釋中所述)。爲框架使用pack()來計算正確的大小。
+0

這是問題所在。感謝您的幫助和附加提示。 – ConveniencePatterns

+0

@ConveniencePatterns那麼,你有超過1 :)順便說一下,你的GUI不適合我,因爲它的大小太大,它溢出我的屏幕。看到我的建議,如果你需要幫助,我可以發佈一些代碼。 – user1803551

+0

是的,這是真的。問題2發生在我縮短堆棧溢出的代碼時。問題3絕對是一個我會盡快修復的設計錯誤。你是否因爲它的固定大小而溢出?使GUI大小動態是在我的TODO列表上。 – ConveniencePatterns