How to get the top card in Java's CardLayout

alexcoco picture alexcoco · Dec 10, 2010 · Viewed 10.3k times · Source

Is it possible to get the top card in Java's CardLayout? I've tried looping through each component to check for visibility with isVisible() but it seems that they're all "visible".

Edit: By "top card" I mean the one that's currently at the "top", being displayed, not the first or last cards. Also, I don't know if it helps but I'm looking for a JPanel (or a subclass thereof)

Edit: Code snippet

for (Component component : getComponents()) {
 if (component instanceof JPanel && component.isVisible()) {
  currentPanel = (JPanel) component;
  System.out.println(currentPanel.getClass().getName());
 }
}  

The above code always prints out every component class's name, regardless if they are the visible card or not.

Edit: I'm using this as part of a school assignment. I'm not trying to get a freebie here, the assignment does not revolve around this layout. It just seems to be the most convenient layout for changing between panels. My teacher has specified that there is to be no third party code in the project. I've seen the implementation from camickr's link before but I can't use it. I can loosely implement similar features it and maybe give a reference it in the documentation but I can't simply download and use it.

Edit: The reason I'm trying to get the top card is because I have a toolbar with an "Add" button. Instead of having one add button for each of my two possible things I wanted it to know which to add simply by looking at what panel is currently being viewed. If there is another, more appropriate way to do this please let me know.

Edit: Thanks everyone for helping out. I figured out what the problem was. I guess it was my fault since I didn't provide enough detail. Two of my cards are JScrollPanes and I also needed to look through its contents to find out if one of those panels was the one I was seeing. I didn't check for isVisible() on the scroll pane itself, i had been looking at it's contends that are always visible, it was the scroll pane who's visibility I needed to verify.

public JPanel getCurrentPanel() {
        JPanel currentPanel = null;

        for (Component component : getComponents()) {
            if (component.isVisible()) {
                if (component instanceof JPanel) 
                    currentPanel = (JPanel) component;
                else if (component instanceof JScrollPane)
                    currentPanel = (JPanel) ((JScrollPane) component).getViewport().getComponent(0);
            }
        }

        return currentPanel;
    }

Answer

robert_x44 picture robert_x44 · Dec 10, 2010

If you modify the code snippet you added to the question you can easily tell which card is visible. In my test frame, when the button is pushed, it prints out the name of the currently visible card, before flipping to the next card. Modifying your code, the important thing to keep in mind is that you need to call getComponents() on the component that actually has the CardLayout. That way, only one of its children is visible. I'm guessing in your code you are calling getComponents on the frame that contains your JPanel with CardLayout.

class TestFrame
        extends JFrame
        implements ActionListener
{
    public TestFrame()
    {
        cards = new JPanel(new CardLayout() );
        card_list = new JPanel[5];

        for (int i = 0; i < card_list.length; i++) {
            String text = "Card " + i;
            JPanel card = createCard(text);
            card_list[i] = card;
            cards.add(card, text);
        }

        add(cards);
    }

public JPanel getCurrentCard()
{
    JPanel card = null;

    for (Component comp : cards.getComponents() ) {
        if (comp.isVisible() == true) {
            card = (JPanel)comp;
            System.out.println(card.getName() );
        }
    }
    System.out.println();

    return card;
}

public void actionPerformed(ActionEvent evt)
{
    JPanel card = getCurrentCard();

    CardLayout cl = (CardLayout)(cards.getLayout() );
    cl.next(cards);
}

    public JPanel createCard(String text)
    {
        JPanel card = new JPanel();
        card.setName(text);

        JButton btn = new JButton(text);
        btn.addActionListener(this);

        card.add(btn);
        return card;
    }

    JPanel cards;
    JPanel[] card_list;
}

In the actionPerformed() method, I printed the name of the card, but you have a reference to the currently visible card.