1

I have a card layout, first card is a menu.

I Select the second card, and carry out some action. We'll say add a JTextField by clicking a button. If I return to the menu card, and then go back to the second card, that JTextField I added the first time will still be there.

I want the second card to be as I originally constructed it each time I access it, with the buttons, but without the Textfield.

Peddler
  • 6,045
  • 4
  • 18
  • 22
  • If *"as it was originally constructed"* means 'blank/no components' then it seems to make more sense to add new cards. – Andrew Thompson Mar 16 '12 at 16:34
  • Simply use [removeLayoutComponent(...)](http://docs.oracle.com/javase/7/docs/api/java/awt/CardLayout.html#removeLayoutComponent(java.awt.Component)), to remove the present card from the `Layout`, on previous button click and then add a new instance of the card by using [addLayoutComponent(...)](http://docs.oracle.com/javase/7/docs/api/java/awt/CardLayout.html#addLayoutComponent(java.awt.Component, java.lang.Object)). – nIcE cOw Mar 16 '12 at 16:34
  • @AndrewThompson maybe I was unclear... My second card, would have buttons on it, when these buttons are clicked a TextField Appears, and if I return to the first card, and then go back to the second card again, the textfield will still be there. I want the second card to be as I originally constructed it each time I access it, with the buttons, without the Textfield – Peddler Mar 16 '12 at 16:48
  • @GagandeepBali See above Comment. – Peddler Mar 16 '12 at 17:06
  • 1
    @Peddler : I am actually working on this thing, I just realized your problem as I was testing it :-) – nIcE cOw Mar 16 '12 at 18:07
  • @Peddler : Congrats, seems to me you had found a bug in `CardLayout` :-), seems to me as you remove a `Component` from the `CardLayout`, it becomes unstable, useless I must say. One person had even reported this [here](http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4546123). I just don't know how to reach out to Java with this bug, as I am using JDK 1.7 and the issue still persists. Hope someone can guide me through this. – nIcE cOw Mar 16 '12 at 18:42
  • @Gangan and the OP: What if you call `revalidate()` and perhaps `repaint()` on the container that uses the CardLayout since this will tell the layout to reposition its components? – Hovercraft Full Of Eels Mar 16 '12 at 19:35
  • @HovercraftFullOfEels Same story if you call revalidate or repaint! It's kind of weird really! – Peddler Mar 16 '12 at 20:15
  • 1
    It'd be great if you could create and post an [sscce](http://sscce.org). – Hovercraft Full Of Eels Mar 16 '12 at 20:17
  • As soon as I get a bit of time I will! – Peddler Mar 17 '12 at 10:57
  • @HovercraftFullOfEels : I had tried it, and removing a `Card` from the `CardLayout` gives wicked results, sometimes it won't delete at all . – nIcE cOw Mar 19 '12 at 16:46
  • @GagandeepBali: Whenever I've tried this, it has worked out fine. Can *you* post an sscce, though it would have to be as an answer? – Hovercraft Full Of Eels Mar 19 '12 at 17:09
  • @HovercraftFullOfEels : Please have a look, I just tried to recreate the situation, have a look at the code. – nIcE cOw Mar 19 '12 at 17:37
  • @GagandeepBali _Simply use removeLayoutComponent(...)_ no, that's wrong (don't know how you came to that unusual idea ;-): the way to remove a component from the hierarchy is to remove it from its parent is ... to call parent.remove(child) – kleopatra Mar 20 '12 at 09:56
  • not only the cards get confused, me too: OP wants to remove a _component from a card_, while @GagandeepBali (and the bug report) are removing a _complete card_ ? – kleopatra Mar 20 '12 at 10:02
  • @kleopatra : Yeah true, that bug comes when removing the whole card using the `CardLayout`s method. We use `CardLayout` for simplicity. Those two methods in `CardLayout` `addXXX()` and `removeXXX()` do nothing, except for creating havoc :-) – nIcE cOw Mar 20 '12 at 10:09
  • @GagandeepBali sure they do something: exactly what they have to (cleanup the layout itself _not_ the component they are controlling) - they are _not_ for usage in application code! Or in other words - repeating myself - it's not a bug in the layout, it's an error in _your_ application code – kleopatra Mar 20 '12 at 10:14
  • @kleopatra : But even if you use `removeXXX()` of `CardLayout` and then you do `revalidate()` and `repaint()` on the `JPanel`, still the same problem will come. Now in this latest edit, even though I never conveyed it to the `CardLayout` that I had removed something, other than removing the whole thing from the `JPanel` itself, so shouldn't it becomes the duty of the `CardLayout` to atleast throw some `Exception` – nIcE cOw Mar 20 '12 at 10:24
  • to be continued : as to something extraordinary had happened, without my knowledge, since I am the one managing the Components, and someone else removed something, but not through me :-) , in the same manner as we add it to the `CardLayout`. – nIcE cOw Mar 20 '12 at 10:24
  • @kleopatra : The OP said, he wants the `Card` to revert back to it's original form, at each visit to the same card, after modifications. So seems like he needs to remove the old card with modifications. – nIcE cOw Mar 20 '12 at 10:28

2 Answers2

1

Make sure the panel you're trying to reset has code that takes it back to its "as it was originally constructed" state. Then, when you process the whatever event that causes you to change cards, call that code to restore the original state before showing the card.

Eric Hydrick
  • 3,467
  • 2
  • 28
  • 41
1

Here is the final sorted out version, to remove the card, after doing changes to it, have a look, use the revalidate() and repaint() thingy as usual :-)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ApplicationBase extends JFrame
{
    private JPanel centerPanel;
    private int topPanelCount = 0;

    private String[] cardNames = {
                                                        "Login Window",
                                                        "TextField Creation"
                                                   };

    private TextFieldCreation tfc;
    private LoginWindow lw;

    private JButton nextButton;
    private JButton removeButton;

    private ActionListener actionListener = new ActionListener()
    {
        public void actionPerformed(ActionEvent ae)
        {
            if (ae.getSource() == nextButton)
            {   
                    CardLayout cardLayout = (CardLayout) centerPanel.getLayout();
                    cardLayout.next(centerPanel);
            }
            else if (ae.getSource() == removeButton)
            {
                    centerPanel.remove(tfc);
                    centerPanel.revalidate();
                    centerPanel.repaint();
                    tfc = new TextFieldCreation();
                    tfc.createAndDisplayGUI();  
                    centerPanel.add(tfc, cardNames[1]);
            }
        }
    };

    private void createAndDisplayGUI()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationByPlatform(true);

        centerPanel = new JPanel();
        centerPanel.setLayout(new CardLayout());

        lw = new LoginWindow();
        lw.createAndDisplayGUI();
        centerPanel.add(lw, cardNames[0]);
        tfc = new TextFieldCreation();
        tfc.createAndDisplayGUI();
        centerPanel.add(tfc, cardNames[1]);

        JPanel bottomPanel = new JPanel();
        removeButton = new JButton("REMOVE");
        nextButton = new JButton("NEXT");       
        removeButton.addActionListener(actionListener);
        nextButton.addActionListener(actionListener);

        bottomPanel.add(removeButton);
        bottomPanel.add(nextButton);

        add(centerPanel, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.PAGE_END);

        pack();
        setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new ApplicationBase().createAndDisplayGUI();
            }
        });
    }
}

class TextFieldCreation extends JPanel
{
    private JButton createButton;
    private int count = 0;

    public void createAndDisplayGUI()
    {
        final JPanel topPanel = new JPanel();
        topPanel.setLayout(new GridLayout(0, 2));

        createButton = new JButton("CREATE TEXTFIELD");
        createButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                JTextField tfield = new JTextField();
                tfield.setActionCommand("JTextField" + count);

                topPanel.add(tfield);
                topPanel.revalidate();
                topPanel.repaint();
            }
        });

        setLayout(new BorderLayout(5, 5));
        add(topPanel, BorderLayout.CENTER);
        add(createButton, BorderLayout.PAGE_END);
    }
}

class LoginWindow extends JPanel
{
    private JPanel topPanel;
    private JPanel middlePanel;
    private JPanel bottomPanel;

    public void createAndDisplayGUI()
    {
        topPanel = new JPanel();

        JLabel userLabel = new JLabel("USERNAME : ", JLabel.CENTER);
        JTextField userField = new JTextField(20);
        topPanel.add(userLabel);
        topPanel.add(userField);

        middlePanel = new JPanel();

        JLabel passLabel = new JLabel("PASSWORD : ", JLabel.CENTER);
        JTextField passField = new JTextField(20);
        middlePanel.add(passLabel);
        middlePanel.add(passField);

        bottomPanel = new JPanel();

        JButton loginButton = new JButton("LGOIN");
        bottomPanel.add(loginButton);

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(topPanel);
        add(middlePanel);
        add(bottomPanel);
    }
}

If you just wanted to remove the Latest Edit made to the card, try this code :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ApplicationBase extends JFrame
{
    private JPanel centerPanel;
    private int topPanelCount = 0;

    private String[] cardNames = {
                                                        "Login Window",
                                                        "TextField Creation"
                                                   };

    private TextFieldCreation tfc;
    private LoginWindow lw;

    private JButton nextButton;
    private JButton removeButton;

    private ActionListener actionListener = new ActionListener()
    {
        public void actionPerformed(ActionEvent ae)
        {
            if (ae.getSource() == nextButton)
            {   
                    CardLayout cardLayout = (CardLayout) centerPanel.getLayout();
                    cardLayout.next(centerPanel);
            }
            else if (ae.getSource() == removeButton)
            {
                    TextFieldCreation.topPanel.remove(TextFieldCreation.tfield);
                    TextFieldCreation.topPanel.revalidate();
                    TextFieldCreation.topPanel.repaint();
            }
        }
    };

    private void createAndDisplayGUI()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationByPlatform(true);

        centerPanel = new JPanel();
        centerPanel.setLayout(new CardLayout());

        lw = new LoginWindow();
        lw.createAndDisplayGUI();
        centerPanel.add(lw, cardNames[0]);
        tfc = new TextFieldCreation();
        tfc.createAndDisplayGUI();
        centerPanel.add(tfc, cardNames[1]);

        JPanel bottomPanel = new JPanel();
        removeButton = new JButton("REMOVE");
        nextButton = new JButton("NEXT");       
        removeButton.addActionListener(actionListener);
        nextButton.addActionListener(actionListener);

        bottomPanel.add(removeButton);
        bottomPanel.add(nextButton);

        add(centerPanel, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.PAGE_END);

        pack();
        setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new ApplicationBase().createAndDisplayGUI();
            }
        });
    }
}

class TextFieldCreation extends JPanel
{
    private JButton createButton;
    private int count = 0;
    public static JTextField tfield;
    public static JPanel topPanel;

    public void createAndDisplayGUI()
    {
        topPanel = new JPanel();
        topPanel.setLayout(new GridLayout(0, 2));

        createButton = new JButton("CREATE TEXTFIELD");
        createButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                tfield = new JTextField();
                tfield.setActionCommand("JTextField" + count);

                topPanel.add(tfield);
                topPanel.revalidate();
                topPanel.repaint();
            }
        });

        setLayout(new BorderLayout(5, 5));
        add(topPanel, BorderLayout.CENTER);
        add(createButton, BorderLayout.PAGE_END);
    }
}

class LoginWindow extends JPanel
{
    private JPanel topPanel;
    private JPanel middlePanel;
    private JPanel bottomPanel;

    public void createAndDisplayGUI()
    {
        topPanel = new JPanel();

        JLabel userLabel = new JLabel("USERNAME : ", JLabel.CENTER);
        JTextField userField = new JTextField(20);
        topPanel.add(userLabel);
        topPanel.add(userField);

        middlePanel = new JPanel();

        JLabel passLabel = new JLabel("PASSWORD : ", JLabel.CENTER);
        JTextField passField = new JTextField(20);
        middlePanel.add(passLabel);
        middlePanel.add(passField);

        bottomPanel = new JPanel();

        JButton loginButton = new JButton("LGOIN");
        bottomPanel.add(loginButton);

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(topPanel);
        add(middlePanel);
        add(bottomPanel);
    }
}
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • What if you don't remove the component from the CardLayout, but rather remove it from the container itself (the centerPanel)? – Hovercraft Full Of Eels Mar 19 '12 at 21:28
  • @HovercraftFullOfEels : Yeah removing it directly from the `centerPanel` worked fine as expected. So somewhere `CardLayout` is not performing as it should be :-) Thankyou for taking time to have a look at the code. – nIcE cOw Mar 20 '12 at 04:40
  • it's not a bug, it's a user error (IMO, might be I don't quite understand it :) the way to remove a component from its parent is _always_ to call parent.remove(...) which internally messages the layout.removeLayoutComponent which cleans up itself. So if application code calls the latter, the component is still in the parent's child tree which may or may not confuse some collaborator. @Hovercraft good catch :-) – kleopatra Mar 20 '12 at 09:51
  • But the question arises, when such things are to be done by hand, I mean manually, then what those two methods are for, they do remove sometimes, God Knows, seems like they are moody in doing their work :-). It's surely a bug, otherwise why to use `CardLayout` why not do it the old style, when we have to do `revalidate()` and `repaint()` while removing a card, why not do the same thing for adding a card too. – nIcE cOw Mar 20 '12 at 10:13
  • 1
    they are for usage by the framework itself, that is by the _container_ - **NOT** for application code. All LayoutManagers have those methods, but _you_ never use them - so why do you think you should in the case of CardLayout .. **SIMPLY DON'T** – kleopatra Mar 20 '12 at 10:26
  • Might be you are right, but I guess it raised some questions, as usual :-) , so I might ponder over them for a while and try to reach my doubts :-) . – nIcE cOw Mar 20 '12 at 10:31
  • downvoted for muddying the waters (IMO the OP wants to restore the _contents of a card_ while this tries to answer _removing a whole card_). – kleopatra Mar 20 '12 at 10:57
  • @kleopatra : No No, OP wants to get the original card, he/she doesn't wants to remove the components one by one, he wants his original card back as added to the `CardLayout` in the start. As stated by him/her in the question "I want the second card to be as I originally constructed it each time I access it, with the buttons" – nIcE cOw Mar 20 '12 at 11:15
  • the change of the second was: _add a JTextField_ - so being _as originally constructed_ amounts to a simple remove of that textField :-) But agree that the question is not very clear, so let's wait until the OP clarifies – kleopatra Mar 20 '12 at 14:13