2016-07-25 80 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