Site Search:

Swing EventDispatchThread

<Back

EventQueue.java stores prioritized events in an array of queues. It accepts events from the multiple event producers -- SWING components, keyboard activity, mouse activity etc. EventQueue starts a thread -- EventDispachThread -- as the only event consumer. The EventDispachThread takes one event at a time from the EventQueue and process it.



EventQueue.java


      
    /*
     * We maintain one Queue for each priority that the EventQueue supports.
     * That is, the EventQueue object is actually implemented as
     * NUM_PRIORITIES queues and all Events on a particular internal Queue
     * have identical priority. Events are pulled off the EventQueue starting
     * with the Queue of highest priority. We progress in decreasing order
     * across all Queues.
     */

     private Queue[] queues = new Queue[NUM_PRIORITIES];

     private EventDispatchThread dispatchThread;
        
     final void initDispatchThread() {

        pushPopLock.lock();
        try {
            if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
                dispatchThread = AccessController.doPrivileged(
                    new PrivilegedAction<EventDispatchThread>() {
                        public EventDispatchThread run() {
                            EventDispatchThread t =
                                new EventDispatchThread(threadGroup,
                                                        name,
                                                        EventQueue.this);
                            t.setContextClassLoader(classLoader);
                            t.setPriority(Thread.NORM_PRIORITY + 1);
                            t.setDaemon(false);
                            AWTAutoShutdown.getInstance().notifyThreadBusy(t);
                            return t;
                        }
                    }
                );
                dispatchThread.start();
            }
        } finally {
            pushPopLock.unlock();
        }
    }

    /**
     * Called from dispatchEvent() under a correct AccessControlContext
     */
    private void dispatchEventImpl(final AWTEvent event, final Object src) {
        event.isPosted = true;
        if (event instanceof ActiveEvent) {
            // This could become the sole method of dispatching in time.
            setCurrentEventAndMostRecentTimeImpl(event);
            ((ActiveEvent)event).dispatch();
        } else if (src instanceof Component) {
            ((Component)src).dispatchEvent(event);
            event.dispatched();
        } else if (src instanceof MenuComponent) {
            ((MenuComponent)src).dispatchEvent(event);
        } else if (src instanceof TrayIcon) {
            ((TrayIcon)src).dispatchEvent(event);
        } else if (src instanceof AWTAutoShutdown) {
            if (noEvents()) {
                dispatchThread.stopDispatching();
            }
        } else {
            if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
                eventLog.fine("Unable to dispatch event: " + event);
            }
        }

    }

EventDispatchThread.java is a thread keep pumping events from EventQueue and processing it -- call event.consume() and eq.dispatchEvent(event).

class EventDispatchThread extends Thread {

    private EventQueue theQueue;

    EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
        super(group, name);
        setEventQueue(queue);
    }

    public void run() {
        try {
            pumpEvents(new Conditional() {
                public boolean evaluate() {
                    return true;
                }
            });
        } finally {
            getEventQueue().detachDispatchThread(this);
        }

    }

An event (e.g. KeyEvent) can have many listeners, (e.g. GameBoard class that implements KeyListener). Upon notifying, listeners will take actions accordingly (e.g. println, shoot and repaint).
VehicalTrackerDemo.java


class GameBoard extends JPanel implements KeyListener {

    @Override
    public void keyTyped(KeyEvent e) {
        System.out.println(e.getKeyCode());
        shoot();
        repaint();
    }

Component.java allows the listeners to take action on a KeyEvent.

    
    protected void processKeyEvent(KeyEvent e) {
        KeyListener listener = keyListener;
        if (listener != null) {
            int id = e.getID();
            switch(id) {
              case KeyEvent.KEY_TYPED:
                  listener.keyTyped(e);
                  break;
              case KeyEvent.KEY_PRESSED:
                  listener.keyPressed(e);
                  break;
              case KeyEvent.KEY_RELEASED:
                  listener.keyReleased(e);
                  break;
            }
        }

    }