Java, BorderLayout.CENTER, получение ширины и высоты JPanel - PullRequest
4 голосов
/ 19 июня 2011

Я использую Swing и AWT (для слушателей), чтобы сделать небольшую программу. У меня проблема с получением размера моей JPanel (класс с именем Chess). Мой макет:

public class Main extends JFrame implements MouseListener, ActionListener{

    Chess chessPanel = new Chess ();
    JButton newGameButton = new JButton ("New Game");
    JButton loadGameButton = new JButton ("Load Game");
    JButton saveGameButton = new JButton ("Save Game");
    JButton exitButton = new JButton ("Exit");

    public static void main (String [] args) {
        new Main();
    }

    Main () {
        super ("Chess");
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        setSize(dim);
        setLocation(0,0);
        setUndecorated(true);

        chessPanel.addMouseListener(this);
        add(chessPanel, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new FlowLayout());


        newGameButton.addActionListener(this);
        loadGameButton.addActionListener(this);
        saveGameButton.addActionListener(this);
        exitButton.addActionListener(this);

        buttonPanel.add(newGameButton);
        buttonPanel.add(loadGameButton);
        buttonPanel.add(saveGameButton);
        buttonPanel.add(exitButton);

        add(buttonPanel, BorderLayout.SOUTH);

        setVisible(true);
    }

    // ... Code ...
}

Как вы можете видеть по коду, у меня есть один JPanel в ЦЕНТРЕ, который занимает почти весь экран. Внизу у меня есть еще один JPanel (ЮГ), который имеет ряд кнопок.

Мне нужен размер, который принимает JPanel в ЦЕНТРЕ. Когда я вызываю методы getWidth (), getHeight () или getBounds (), унаследованные от JPanel, все они возвращают 0 из-за BorderLayout. Есть идеи, как получить реальные значения?

PS: экран всегда занимает весь экран, и его размер никогда не изменится, если это поможет.

1 Ответ

7 голосов
/ 19 июня 2011

Скорее всего, вы вызываете getWidth до рендеринга JPanel, и поэтому он будет равен 0. Решение состоит в том, чтобы получить размер после рендеринга, например, после pack () или setVisible (true)был вызван в корневом контейнере, который содержит этот JPanel.

Кроме того, я рекомендую не вызывать setSize () для чего-либо, так как большинство стандартных менеджеров компоновки наблюдают предпочтительный размер компонента, а не размер, и когдаВы вызываете pack (), чтобы сказать менеджерам компоновки делать свое дело, установленные размеры обычно игнорируются.Возможно, вы захотите, чтобы ваша JPanel, которая находится в центре, установила свой собственный размер, переопределив его метод setPreferredSize, если он должен быть определенного размера.Затем позвольте JFrame и его удерживаемым контейнерам устанавливать размер подгонки ставки на основе их менеджеров раскладки, когда вы вызываете пакет.

например,

import java.awt.*;
import javax.swing.*;

public class Main extends JFrame {

   Chess chessPanel = new Chess();
   JButton newGameButton = new JButton("New Game");
   JButton loadGameButton = new JButton("Load Game");
   JButton saveGameButton = new JButton("Save Game");
   JButton exitButton = new JButton("Exit");

   public static void main(String[] args) {
      new Main();
   }

   Main() {
      super("Chess");
      add(chessPanel, BorderLayout.CENTER);

      JPanel buttonPanel = new JPanel();
      buttonPanel.setLayout(new FlowLayout());

      buttonPanel.add(newGameButton);
      buttonPanel.add(loadGameButton);
      buttonPanel.add(saveGameButton);
      buttonPanel.add(exitButton);

      System.out.printf("chessPanel Size before rendering: %s%n", chessPanel.getSize());
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      add(buttonPanel, BorderLayout.SOUTH);
      pack();
      System.out.printf("chessPanel Size after rendering: %s%n", chessPanel.getSize());
      setLocationRelativeTo(null);
      setVisible(true);
   }

   // ... Code ...
}

@SuppressWarnings("serial")
class Chess extends JPanel {
   private static final int CHESS_WIDTH = 600;
   private static final int CHESS_HEIGHT = CHESS_WIDTH;
   private static final int MAX_ROW = 8;
   private static final int MAX_COL = 8;
   private static final Color LIGHT_COLOR = new Color(240, 190, 40);
   private static final Color DARK_COLOR = new Color(180, 50, 0);

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(CHESS_WIDTH, CHESS_HEIGHT);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      int panelWidth = getWidth();
      int panelHeight = getHeight();
      int sqrWidth = panelWidth / MAX_ROW;
      int sqrHeight = panelHeight / MAX_COL;
      for (int row = 0; row < MAX_ROW; row++) {
         for (int col = 0; col < MAX_COL; col++) {
            Color c = (row % 2 == col % 2) ? LIGHT_COLOR : DARK_COLOR;
            g.setColor(c);
            int x = (row * panelWidth) / MAX_ROW;
            int y = (col * panelHeight) / MAX_COL;
            g.fillRect(x, y, sqrWidth, sqrHeight);
         }
      }
   }
}
...