This page looks plain and unstyled because you're using a non-standard compliant browser. To see it in its best form, please upgrade to a browser that supports web standards. It's free and painless.

Robert Marcano's blog
Get Firefox Use OpenOffice.org hacker emblem

Disabling Keyboard Input - Swing

robert | 09 June, 2005 17:11

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

Add comment

 authimage
 
Valid XHTML 1.0 Strict and CSS.
Copyright 2003-2007 Robert Marcano. All Rights Reserved
Powered by LifeType
Original Design by Book of Styles