Reputation: 244
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
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
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