Java — графический интерфейс, панель и доступ к данным

Я делаю игру с тремя основными панелями и несколькими подпанелями, и я не понимаю, как вы «соединяете» панели и их данные.

У меня есть основной класс, который расширяет JFrame и добавляет три панели JPanel. Каждая из этих панелей является подклассом JPanel. (Пример: JPanel gameControlPanel = new GameControlPanel(), где GameControlPanel — это класс, который я создал для расширения JPanel.)

Теперь все игровые данные (такие как состояние игры и два массива, в которых хранятся сохраненные игроки и сохраненные результаты) находятся на игровой панели. Но мне нужно получить и установить эти данные с двух других панелей. И как это сделать ускользает от меня.

** Итак, мой вопрос: как мне это сделать? Как я могу получить доступ к данным в одном подклассе JPanel из другого подкласса JPanel (который имеет тот же родительский JFrame)?


Если это поможет, это код расширенного класса JFrame, где я добавляю три панели...:

    JPanel controlButtonsPanel = new GameControlButtons();
    controlButtonsPanel.setPreferredSize(new Dimension(801,60));
    controlButtonsPanel.setBorder(new LineBorder(Color.white, 1));
    constraints.anchor = GridBagConstraints.NORTHWEST;
    constraints.weightx = 2;
    constraints.weighty = 0.3;
    this.add(controlButtonsPanel, constraints);

    JPanel gameDataPanel = new GameDataPanel();
    gameDataPanel.setPreferredSize(new Dimension(500,838));
    gameDataPanel.setBorder(new LineBorder(Color.white, 2));
    constraints.anchor = GridBagConstraints.NORTHEAST;
    constraints.weightx = 1;
    constraints.weighty = 2;
    this.add(gameDataPanel, constraints);

    JPanel graphicsPanel = new RoofRunnerGame("Ken");
    constraints.anchor = GridBagConstraints.SOUTHWEST;
    constraints.weightx = 2;
    constraints.weighty = 1;
    graphicsPanel.setBorder(new LineBorder(Color.white, 1));
    graphicsPanel.setPreferredSize(new Dimension(800,800));
    graphicsPanel.requestFocus();
    this.add(graphicsPanel, constraints);       

GraphicsPanel содержит все эти данные:

private ArrayList<Player> savedPlayers;                                     // Holds saved data for player's who paused and exited game.
private ArrayList<Player> savedScores;                                      // Holds high scores from player's who played game and died.
private ArrayList<Birds> birdList = new ArrayList<Birds>();                 // Not serialized due to its randomness and unimportance to player.
private ArrayList<Clouds> cloudList = new ArrayList<Clouds>();              // Not serialized due to its randomness and unimportance to player.
private Player gamePlayer;                                                  // Player object that holds all data for a game instance.

И я хочу получить доступ к этим данным из двух других панелей (класса gameDataPanel и класса gameControlButton).


person Dan James    schedule 04.10.2010    source источник


Ответы (3)


Изучите шаблон Контроллер представления модели. Сохраните состояние игры и данные в модели и используйте наблюдатели или прослушиватели, чтобы уведомлять компоненты пользовательского интерфейса об изменениях в данных.

Например, если вы следуете тому, как был реализован Swing, определите интерфейс слушателя следующим образом:

public interface PlayersListener {
    void playerSaved(Player player);
}

Тогда вместо списка сохраненных игроков у вас может быть класс Players, подобный этому:

public class Players {
    private List<PlayersListener> listeners = ...;
    private List<Player> players = ...;

    public void addPlayersListener(PlayersListener listener) {
        if (!listeners.contains(listener)) {
            listeners.add(listener);
        }
    }

    public voi removePlayerListener(PlayerListener listener) {
        listeners.remove(listener);
    }

    public voi savePlayer(Player player) {
        players.add(player);
        for (PlayerListener listener : listeners) {
            listener.playerSaved(player);
        }

Когда вы создаете новую панель, которой нужно наблюдать за сохраненными игроками, вы можете просто передать экземпляр класса Players панелям в конструкторе:

controlButtonsPanel = new GameControlButtons(players);
..
gameDataPanel = new GameDataPanel(players);

А внутри конструктора просто зарегистрируйте панель как прослушиватель players.

Таким образом, всякий раз, когда что-то сохраняет игрока, независимо от того, какой это компонент/класс, все заинтересованные стороны получат уведомление об изменениях. И обязательно передайте один и тот же экземпляр Players на все панели.

На самом деле так же работают компоненты Swing, если вы посмотрите, например, на JPanel, у него есть несколько разных методов addSomethingListener. Слушатели — это классы, которые реализуют определенный интерфейс слушателя. И модели взаимозаменяемы во многих компонентах, например, JTable использует TableModel, которая, в свою очередь, также определяется как интерфейс. Однако в вашем случае вам, вероятно, не нужно использовать разные реализации модели.

person fish    schedule 04.10.2010

Данные должны храниться в модели, которая совместно используется частями пользовательского интерфейса, используйте панели пользовательского интерфейса только для представления. Используйте шаблон наблюдателя, чтобы уведомить представление пользовательского интерфейса об изменениях в модели.

person Michael Spector    schedule 04.10.2010
comment
Я не понимаю. Видите, у меня есть все данные, и я хочу представить их на других панелях. Я просто не знаю, как его получить, чтобы представить. - person Dan James; 04.10.2010
comment
Не могли бы вы привести пример того, как бы вы сделали мою программу: какой класс будет расширять JFrame и JPanels и как они будут связаны? - person Dan James; 04.10.2010
comment
Прочтите эту статью: java.sun.com/products/jfc/tsc/ статьи/архитектура - person Michael Spector; 04.10.2010

Вы сказали, что хотите отображать некоторую информацию более чем на одной из панелей? Вы можете создать глобальный класс для статического хранения этих данных, а затем получить доступ к этой информации из других ваших классов, используя методы get...(); и set...();.

Пример:

public class Global
 {
     private static Object objectName;

     public Object getObjectName()
     {
         return objectName;
     }

     public void setObjectName(Object objectName)
     {
         this.objectName = objectName;
     }
}

Дайте мне знать, если мне нужно уточнить дальше.

person Zéychin    schedule 04.10.2010