Paulywog
Paulywog

Reputation: 244

How to remove JButton from JFrame from inside JButton's ActionListener?

I always have trouble with this when coding my Swing applications, I figured I'd finally get a definative answer instead of playing around with it until I get it working...

I have a JFrame. Inside this JFrame is a JButton. In the ActionListener I want to almost empty the JFrame leaving one or two components (which would include removing the JButton). The application then freezes because you can't remove the component until it's ActionListener finishes. How do I get around that?

Upvotes: 2

Views: 2911

Answers (2)

tenorsax
tenorsax

Reputation: 21233

Don't forget to call validate() and repaint() on the container when you're removing components and should work OK.

import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class RemoveDemo {

    static class RemoveAction extends AbstractAction{
        private Container container;

        public RemoveAction(Container container){
            super("Remove me");
            this.container = container;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            container.remove((Component) e.getSource());
            container.validate();
            container.repaint();    
        }
    }

    private static void createAndShowGUI() {
        final JFrame frame = new JFrame("Demo");
        frame.setLayout(new FlowLayout());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        RemoveAction action = new RemoveAction(frame);
        frame.add(new JButton(action));
        frame.add(new JButton(action));

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

Upvotes: 6

trashgod
trashgod

Reputation: 205885

Use EventQueue.invokeLater() to add a suitable Runnable in the event queue. It "will happen after all pending events are processed."

Upvotes: 3

Related Questions