views:

56

answers:

3

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. Each of those panels is a subclass of JPanel. (Ex: JPanel gameControlPanel = new GameControlPanel(), where GameControlPanel is a class I created to extend 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)?


If it helps, this is the extended JFrame class's code, where I add the three panels...:

    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:

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

A: 

Data should be stored in a model that is shared between UI parts, use UI panels only for presentation. Use observer pattern to notify UI presentation about changes in model.

spektom
I don't understand. See, I have all the data, and want to present it in the other panels. I just don't know how to *get* it so I can present it.
Dan James
Could you give me an example of how you would make my program: which class would extend JFrame and JPanels, and how would they be connected?
Dan James
Please read this article: http://java.sun.com/products/jfc/tsc/articles/architecture/
spektom
+3  A: 

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.

For example, if you follow the way Swing has been implemented, define a listener interface like this:

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

Then, instead of the savedPlayers list you could have a class Players similar to this:

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:

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

And inside the constructor just register the panel as a listener to 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.

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. 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. However in your case you probably don't need to be able to use different model implementations.

fish
A: 

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...(); and 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.

Zéychin