AncientSwordRage
AncientSwordRage

Reputation: 7618

How can I get my cardLayout to work?

I am attempting to develop a LARP character manager, and I have inside my frame, a panel to contain all the windows I want to swap through using CardLayout. Here is my code for the ContainerPane.

public class ContainerPane extends JPanel {
    private static final long serialVersionUID = -4799973935806714569L;
    private JPanel deckOfPanes = null;
    private PlayerManagerPane myPlayerManagerPane = null;
    private GameManagerPane myGameManagerPane= null;
    private CharacterManagerPane myCharacterManagerPane = null;

    final static String CHANGETOCHARACTERMANAGERPANE = "Character Manager";
    final static String CHANGETOPLAYERMANAGERPANE = "Player Manager";
    final static String CHANGETOGAMEMANAGERPANE = "Game Manager";

    public ContainerPane(EventListener myEventListener) {
        myPlayerManagerPane = new PlayerManagerPane(myEventListener);
        myGameManagerPane = new GameManagerPane(myEventListener);
        myCharacterManagerPane = new CharacterManagerPane(myEventListener);
        deckOfPanes= new JPanel(new CardLayout());
        deckOfPanes.add(myCharacterManagerPane,CHANGETOCHARACTERMANAGERPANE);
        deckOfPanes.add(myPlayerManagerPane,CHANGETOPLAYERMANAGERPANE);
        deckOfPanes.add(myGameManagerPane,CHANGETOGAMEMANAGERPANE);

        CardLayout cardLayout = (CardLayout) ((ContainerPane) this).getDeckOfPanes().getLayout();
        cardLayout.show(deckOfPanes,CHANGETOCHARACTERMANAGERPANE);
    }

public JPanel getDeckOfPanes() {
    return deckOfPanes;
}

To start, I'd imagine that the constructor's final line would ensure that when it is called it display's a certain card on top.

Elsewhere in my code I want to swap the cards around, using a menu bar. Here is the code from my EventHandler class:

public void swapView(String key) {
    CardLayout cardLayout = (CardLayout) ((ContainerPane) myContainerPane).getDeckOfPanes().getLayout();
    cardLayout.show(myContainerPane.getDeckOfPanes(),key);
}

This isn't working either. I'm just starting Java and I'd really appreciate any help with this, I've check the tutorials and elsewhere on the web (including stack overflow) and from what I can see, it should be working. Please, any help would be appreciated.

Upvotes: 1

Views: 328

Answers (2)

rtheunissen
rtheunissen

Reputation: 7435

Source (my new blog): http://goo.gl/SDHvX

I've come across many answers on SO suggesting that developers should use CardLayout to switch between views or panels. I know that it works and isn't difficult to implement, but I don't believe that CardLayout is the most appropriate way to do this. I've written a starting point for a class I'm calling ViewSwitcher which takes care of switching views within a JFrame. If you take out the comments you'll see that it's actually a very small class and it's easy to use. Feel free to add try / catch blocks for when a requested view has not been registered (ie. avoid NullPointerException)

You can also consider adding onShow() and onHide() methods to an interface called View and change all instances of Container to View. This would allow for future extensions to handling view switches - something that CardLayout may not be able to offer.

import java.awt.BorderLayout;  
import java.awt.Container;  
import java.util.HashMap;  
import javax.swing.JFrame;  

/**  
 * Used to switch views within a JFrame.  
 *  
 * @author FHMP  
 */    
public class ViewSwitcher {    

    /**  
     * Map to keep track of views according to their specified names  
     */    
    private HashMap<String, Container> views = new HashMap<>();    
    /**  
     * The host container that contains the views to be switched between  
     */    
    private Container host;    
    /**  
     * Used to keep track of the current view  
     */    
    private Container current;    

    /**  
     * Registers a view bound to a specified name  
     *   
     * @param name the name of the view  
     * @param view the view  
     */    
    public void registerView(Container view, String name) {    
        views.put(name, view);    
    }    

    /**  
     * Sets the host container that will contain the view 
     *   
     * @param host the host container  
     */    
    public void setHost(Container host) {    
        this.host = host;    
    }    

    /**  
     * Switches to the view bound to the specified name  
     *   
     * @param name the name of the view to switch to  
     */    
    public void switchTo(String name) {    
        Container view = views.get(name);    

        if(current != null){
           if(current == view) return;
           host.remove(current);   
        }  
        current = view;  

        host.add(view, BorderLayout.CENTER);    
        host.validate();    
        host.repaint(); // just to make sure      
    }    
}  

It's easy to adapt if you need to and the switching is very efficient. In one of my applications I use constant fields for each view instead of having to register each view dynamically by loading them into a map. This example just serves to demonstrate the idea of removing / adding components rather than using CardLayout. You can use it like this:

// JPanels a, b, c already initialised  
// JFrame frame is the main window  

ViewSwitcher switcher = new ViewSwitcher();  

switcher.setHost(frame);  

switcher.registerView(a, "menu");  
switcher.registerView(b, "main");  
switcher.registerView(c, "help");  

switcher.switchTo("help");  
switcher.switchTo("main");  

Upvotes: 1

Reimeus
Reimeus

Reputation: 159754

You have not added deckOfPanes to your ContainerPane. Add:

    deckOfPanes = new JPanel(cardLayout);
    add(deckOfPanes); 
    // etc. 

Upvotes: 5

Related Questions