Best way to block all GUI input without displaying a dialog?
I'd like to achieve what is essentially the same functionality as a modal dialog but without using one. How would you go about blocking all input to a Swing component and it's ancestors? I tried walking up the containment heirarchy and adding my "wait screen" to the layered pane above everything else. Adding mouse and key listeners that consume all events seems to take care ofmost input, but hitting tab still changes focus and I'm not sure what other pitfalls await.
So what would the preferred way of handling this or is it even feasible?
[567 byte] By [
kablaira] at [2007-10-3 8:15:40]

far from best, but this might suit for key input
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Testing
{
boolean wait = false;
public void buildGUI()
{
JPanel p = new JPanel(new BorderLayout());
p.add(new JTextField(10),BorderLayout.NORTH);
p.add(new JTextArea(5,10),BorderLayout.CENTER);
JComboBox cbo = new JComboBox(new String[]{"abc","def","xyz"});
cbo.setEditable(true);
JPanel p1 = new JPanel();
final JButton btn = new JButton("Disable Input");
p1.add(cbo);
p1.add(btn);
p.add(p1,BorderLayout.SOUTH);
JFrame f = new JFrame();
f.getContentPane().add(p);
f.pack();
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
wait = !wait;
btn.setText((wait? "En":"Dis")+"able Input");
}
});
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventDispatcher(new KeyEventDispatcher(){
public boolean dispatchKeyEvent(KeyEvent e){
return wait;
}
});
f.setVisible(true);
}
public static void main (String[] args)
{
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new Testing().buildGUI();
}
});
}
}
also for mouse actions? if so, add a mouseListener to the frame's glasspane,
then toggle the glasspane's visibility
I had actually tried that approach prior to posting and it didn't work. Since you posted it as a suggestion I tried again and it works this time though my code is slightly different:
public boolean dispatchKeyEvent(final KeyEvent e) {
return SwingUtilities.isDescendingFrom(e.getComponent(), component);
}
Where component is the arbitrary JComponent that I'm blocking.
I'm noticing that adding a MouseAdapter and MouseMotionAdapter to the component that's being drawn on top is working now too where it didn't before. I suppose I can only conclude that I had something screwed up before, I have no idea what it could be. Regardless, that combination seems to be the answer and it also seems to only block for anything under my blocking component and not the entire frame which is what I wanted.
Thanks Michael. With that it looks friggin' awesome using some animation and the transparent components I've developed.
This might be another option. Seems to handle all KeyEvents, including tabs:
EventQueue queue = new EventQueue()
{
protected void dispatchEvent(AWTEvent event)
{
if (event.getID() == KeyEvent.KEY_TYPED
|| event.getID() == KeyEvent.KEY_PRESSED
|| event.getID() == KeyEvent.KEY_RELEASED)
{
return;
}
else
super.dispatchEvent(event);
}
};
Toolkit.getDefaultToolkit().getSystemEventQueue().push(queue);
You should be able to handle MouseEvents as well. You can then just pop() the queue to go back to the original (according to the API).