A good programmer using Swing knows that long operations must be executed outside the Swing event dispatch thread, and there are many utlities to do that like the SwingWorker class. One of the problems that arises when another thread in opened to do processing is that sometimes is needed to inhibit any input made by the user. One of the solutions is the usage of the glass pane in order to capture input events, adding a mouse listener to the glass pane we can capture all mouse input events in order to block them.
But what about key events? a key listener works, but is required to transfer the focus to the glass pane, and that remove the focus from the current focused component. For this key events problem I take another approach: use the KeyboardFocusManager. This class allows to install a KeyEventDispatcher that is able to route the event to the appropiate component. If a dispatcher is installed that always returns true, no key event will be sent to any component until the dispatcher is removed. See the following example:
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class TestWindow {
private static JFrame frame;
private static KeyEventDispatcher dispatcher = new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
// returning true will make the KeyboardFocusManager to not send the
// event the component
return true;
}
};
public static void main(String[] args) {
frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// building the components tree
frame.setBounds(0, 0, 400, 400);
JTextField tf = new JTextField();
frame.getContentPane().add(tf);
frame.setVisible(true);
// enter on the text field will call a new thread performing a long
// operation without blocking the swing events dispatch thread
tf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// setting a glass pane
JPanel gp = new JPanel();
gp.setOpaque(false);
frame.setGlassPane(gp);
gp.setVisible(true);
// this empty mouse listener will capture all the mouse events
gp.addMouseListener(new MouseAdapter() {
});
// installing the dispatcher
KeyboardFocusManager kfm = KeyboardFocusManager
.getCurrentKeyboardFocusManager();
kfm.addKeyEventDispatcher(dispatcher);
// starting the thread
Thread t = new LongOperation();
t.start();
}
});
}
private static class LongOperation extends Thread {
public void run() {
try {
// doing someting for a long time
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
// hidding the glass pane
frame.getGlassPane().setVisible(false);
// removing the dispatcher
KeyboardFocusManager kfm = KeyboardFocusManager
.getCurrentKeyboardFocusManager();
kfm.removeKeyEventDispatcher(dispatcher);
}
}
}
Calling the action on the JTextField (enter key) a glass pane will be installed to consume mouse events, and a KeyEventDispatcher to consume key events, next the long operation thread will start. At the end the glass pane and the dispatcher are removed to allow normal processing of the events. In the period that the new thread is executing, no input will be accepted by the user, that was the idea.










Comments (0) |
Trackbacks (0)