问题
I have a CardLayout in which I add cards only as needed. So, when the need arises to show a particular card (identifed by its name), I need a way to check if a card with that name is already present, so that I can either show or create it accordingly.
According to the CardLayout documentation
Flips to the component that was added to this layout with the specified name, using addLayoutComponent. If no such component exists, then nothing happens.
So, no error will be thrown if I ask it to show a card that hasn't been added yet. I couldn't find any API that would let me check if a card is present.
So, is this possible to do? If not how would one go about addressing this? There is the solution that I manually remember what cards I have added but it feels swing should be able to handle this.
回答1:
CardLayout
API provides no way to check if a component has already been added with a given name.
If you really want to do that (but I would strongly advise AGAINST doing that), then you could use reflection on the CardLayout
used by the container, and read its vector
field, then check each entry (of type CardLayout$Card
) for the given name. As you see, that looks like a hack and it could break if CardLayout
was refactored some day (current implementation is quite ugly).
The best way would be for you to directly keep track of the names of all added children in a Set<String>
field somewhere. And this is really not a big deal to do that anyway.
回答2:
So, when the need arises to show a particular card (identifed by its name), I need a way to check if a card with that name is already present, so that I can either show or create it accordingly.
- Get the current component that is displayed in the container
- Attempt to show a different card
- Get the component now displayed in the container
- If the two components are the same, nothing happened and you need to create the card and add it to the container.
This approach will save you managing the Set of cards yourself.
Edit:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CardLayoutTest implements ActionListener
{
JPanel cards;
public void addComponentToPane(Container pane) {
JPanel comboBoxPane = new JPanel();
String comboBoxItems[] = { "Red", "Orange", "Green", "Yellow", "Blue"};
JComboBox cb = new JComboBox(comboBoxItems);
cb.setEditable(false);
cb.addActionListener(this);
comboBoxPane.add(cb);
cards = new JPanel(new CardLayout());
pane.add(comboBoxPane, BorderLayout.PAGE_START);
pane.add(cards, BorderLayout.CENTER);
JPanel red = new JPanel();
red.setBackground(Color.RED);
red.setPreferredSize( new Dimension(200, 50) );
cards.add(red, "Red");
JPanel green = new JPanel();
green.setBackground(Color.GREEN);
green.setPreferredSize( new Dimension(200, 50) );
cards.add(green, "Green");
JPanel blue = new JPanel();
blue.setBackground(Color.BLUE);
blue.setPreferredSize( new Dimension(200, 50) );
cards.add(blue, "Blue");
}
public void actionPerformed(ActionEvent e)
{
Component visible = getVisibleCard();
JComboBox comboBox = (JComboBox)e.getSource();
String item = comboBox.getSelectedItem().toString();
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, item);
// change code below to create and show your card.
if (visible == getVisibleCard())
JOptionPane.showMessageDialog(cards, "Card (" + item + ") not found");
}
private Component getVisibleCard()
{
for(Component c: cards.getComponents())
{
if (c.isVisible())
return c;
}
return null;
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("CardLayoutTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CardLayoutTest demo = new CardLayoutTest();
demo.addComponentToPane(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
来源:https://stackoverflow.com/questions/6040989/check-if-a-card-with-a-name-is-present-in-a-cardlayout