简体   繁体   English

Java-GUI,面板和数据访问

[英]Java - GUI, Panel, and Data Accessing

I'm making a game with three main panels and a few subpanels, and I'm confused about how you "connect" the panels and their data. 我正在制作一个包含三个主面板和几个子面板的游戏,而我对如何“连接”面板及其数据感到困惑。

I have my main class, which extends JFrame and adds three JPanels. 我有主类,它扩展了JFrame并添加了三个JPanels。 Each of those panels is a subclass of JPanel. 每个面板都是JPanel的子类。 (Ex: JPanel gameControlPanel = new GameControlPanel(), where GameControlPanel is a class I created to extend JPanel.) (例如:JPanel gameControlPanel = new GameControlPanel(),其中GameControlPanel是我为扩展JPanel创建的类。)

Now, all the game data (such as the game state, and two arraylists that hold saved players and saved scores) is in the game panel. 现在,所有游戏数据(例如游戏状态以及保存已保存的玩家和已保存的分数的两个数组列表)都在游戏面板中。 But I need to get and set that data from the other two panels. 但是我需要从其他两个面板中获取并设置数据。 And how to do so is evading me. 而如何做却在逃避我。

** So my question is: how do I do this? **所以我的问题是:我该怎么做? How can I access data in one JPanel subclass from another JPanel subclass (that have the same parent JFrame)? 如何从另一个JPanel子类(具有相同的父JFrame)访问一个JPanel子类中的数据?


If it helps, this is the extended JFrame class's code, where I add the three panels...: 如果有帮助,这是扩展的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);       

The graphicsPanel holds all of this data: 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.

And I want to access that data from inside the other two panels (gameDataPanel's class and gameControlButton's class). 我想从其他两个面板(gameDataPanel的类和gameControlButton的类)内部访问该数据。

Study the Model View Controller pattern. 研究模型视图控制器模式。 Store the game state and data to the model, and use Observers or listeners to notify the UI components about the changes in the data. 将游戏状态和数据存储到模型中,并使用观察者或侦听器将有关数据更改的信息通知UI组件。

For example, if you follow the way Swing has been implemented, define a listener interface like this: 例如,如果遵循实现Swing的方式,请定义一个侦听器接口,如下所示:

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

Then, instead of the savedPlayers list you could have a class Players similar to this: 然后,您可以有一个类似于以下类的Players ,而不是savedPlayers列表:

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);
        }

When you create a new Panel that needs to observe the saved players, you can just pass the instance of Players class to the panels in constructor: 当创建一个需要观察保存的玩家的新面板时,您可以将Players类的实例传递给构造函数中的面板:

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

And inside the constructor just register the panel as a listener to players . 在构造函数内部,只需将面板注册为players的侦听器即可。

This way, whenever something saves a player, regardless of which component/class it is, all the interested parties will get notified of the changes. 这样,只要有东西节省了玩家,无论它是哪个组件/类,所有相关方都将得到有关更改的通知。 And make sure to pass in the same instance of Players to all panels. 并确保将Players的相同实例传递给所有面板。

This is actually how the Swing components work too, if you take a look at for example the JPanel, it has a number of different addSomethingListener methods. 实际上,这也是Swing组件的工作方式,例如,如果您查看JPanel,它具有许多不同的addSomethingListener方法。 The listeners are classes that implement a specific listener interface. 侦听器是实现特定侦听器接口的类。 And the models are exchangeable in many of the components, for example JTable uses TableModel, which in turn is also defined as an interface. 而且模型可以在许多组件中互换,例如JTable使用TableModel,而TableModel又被定义为接口。 However in your case you probably don't need to be able to use different model implementations. 但是,根据您的情况,您可能不需要使用其他模型实现。

Data should be stored in a model that is shared between UI parts, use UI panels only for presentation. 数据应存储在UI部件之间共享的模型中,只能将UI面板用于演示。 Use observer pattern to notify UI presentation about changes in model. 使用观察者模式来通知UI演示有关模型的更改。

You said that you want to display some information in more than one of the panels? 您说过要在多个面板中显示一些信息吗? You could make a Global class to hold this data statically, and then access this information from your other classes using get...(); 您可以创建一个Global类来静态保存此数据,然后使用get...();从其他类访问此信息get...(); and set...(); set...(); methods. 方法。

Example: 例:

public class Global
 {
     private static Object objectName;

     public Object getObjectName()
     {
         return objectName;
     }

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

Let me know if I need to elaborate further. 让我知道是否需要进一步阐述。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM