2016-07-25 2 views
1

Я пишу графический интерфейс с Swing. Я использую 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 clas s. Я отметил три строки, где я использовал свой собственный ярлык, который приводит к проблеме макета.

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

* «в основном как шахматная доска» * См. Также [Создание надежного масштабируемого графического интерфейса Swing Chess GUI] (http://stackoverflow.com/q/21142686/418556) для получения советов по компоновке и компонентам (например, например, 'JButton' вместо' JLabel' для каждого квадрата сетки). –

ответ

1

Override

Вы случайно переопределена JComponent#getX() and JComponent#getY(). Значения, возвращаемые этим методом, равны , а не в соответствии со значениями, которые макет может установить внутри (через вызовы setBounds или около того). Это испортит макет.

(Правда, я не очень проверку ли это причина, но это вероятно, и это проблема вообще!)

+0

В этом была проблема. Я сгенерировал геттеры с моей IDE и не понял, что я перепробовал эти методы. Спасибо за помощь. – ConveniencePatterns

3

Есть довольно много вещей, чтобы исправить в вашем кода, но ваша проблема возникает из 3-х вещей:

  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, y).

  3. Порядок, в котором вы вызываете ваши методы, неверен. Во-первых, вы создаете фрейм и показываете его, затем вы меняете его содержимое, добавляя к нему панель с надписями, а затем вы меняете текст на этикетках. Вы должны сделать это наоборот.

Мои рекомендации:

  • Сделайте ваш метод paint быть членом вашего TileLabel класса. Это имеет смысл.
  • Установите значки во время создания меток, если они не известны. Если вы не можете, вам может потребоваться пересчитать требования к пространству.
  • Никогда не делайте свой макет в зависимости от размера экрана или его разрешения. Это создает хрупкий графический интерфейс (как отмечается в комментариях). Используйте pack() для рамки, чтобы рассчитать правильный размер.
+0

В этом была проблема. Спасибо за помощь и дополнительные советы. – ConveniencePatterns

+0

@ConveniencePatterns Ну, у вас было больше 1 :) Кстати, ваш графический интерфейс не работает для меня, потому что размер слишком велик, и он переполняет мой экран. См. Мои рекомендации, и если вам нужна помощь, я могу опубликовать код. – user1803551

+0

Да, это правда. Проблема 2 возникла, когда я сократил свой код для переполнения стека. Проблема 3 - это определенно ошибка дизайна, которую я исправлю как можно скорее. Вы имеете в виду, что он переполняется из-за его фиксированного размера? Изменение динамического размера графического интерфейса в моем списке TODO. – ConveniencePatterns

Смежные вопросы