When and Where to call EventQueue.invokeLater() method

a 夏天 提交于 2021-01-21 11:39:07

问题


I'm totally fresh about threading and GUIs, therefore I couldn't figure out exactly where to call this EventQueue.invokeLater() method.

Am I supposed to call it in every event listeners and something else? What are those "things" to call this method? If so, is there any alternative way to call-once-apply-everywhere method so that It won't take bunch of lines to tuck them to the Event dispatch thread?

Thank you.


回答1:


therefore I couldn't figure out exactly where to call this EventQueue.invokeLater() method.

Swing components need to be updated on the EDT so you would only use invokeLater(...) if you have code executing in a separate Thread and you want to update a GUI component.

Read the section from the Swing tutorial on Concurrency for more information.

As a general rule, unless you are using Threads, you only need to use this method when you create your GUI. Take a look at the FrameDemo from the section in the Swing tutorial on How to Make Frames for a simple example to get you started.

Am I supposed to call it in every event listeners?

No!

All code in an event handler already executes on the Event Dispatch Thread (EDT)so you don't need to invoke this method.




回答2:


Swing is not thread safe. Which means that all interactions with Swing objects should be done via the event thread. Swing does this internally as well, so any time Swing calls an event listener, this will be done on the event thread.

This means two things, firstly, if you ever need to interact with a Swing object, your code should be invoked on the event dispatcher thread.

Also, it means that if you have any code in your event listeners that will run for any noticeable period of time, should be invoked on another thread from your listeners. If you do not do this, then your UI will appear frozen. A SwingWorker object can help with this.




回答3:


To answer your question about needing to check EventQueue.isDispatchThread() that you asked in the some of existing answers' comments:

No, you don't have to check if you are already on the EDT before calling invokeLater().

The SwingUtilities JavaDoc states:

If invokeLater is called from the event dispatching thread -- for example, from a JButton's ActionListener -- the doRun.run() will still be deferred until all pending events have been processed. Note that if the doRun.run() throws an uncaught exception the event dispatching thread will unwind (not the current thread).

Below is further explanation of invokeLater() use.

Notice in ButtonDemo.java that createAndShowGUI() is called using invokeLater(). We must do this because the main() method is not running on the EDT (Event Dispatch Thread). main() is running on its own special main thread that every Java app has.

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}

However in actionPerformed(), the invokeLater() method is not used because here we already on the EDT.

//b1, b2, and b3 are all JButtons
public void actionPerformed(ActionEvent e) {
    if ("disable".equals(e.getActionCommand())) {
        b2.setEnabled(false);
        b1.setEnabled(false);
        b3.setEnabled(true);
    } else {
        b2.setEnabled(true);
        b1.setEnabled(true);
        b3.setEnabled(false);
    }
}

As far as I can recall, Event Listener methods such as actionPerformed() are always called from the EDT. (Sorry I don't know supporting documentation off-hand, and I don't have enough reputation yet to post anymore links anyway. Along with reading the pages linked in camickr's answer, try Google searching for "java tutorial swing introduction event listeners".)

So if you are trying to update a Swing component from a thread other than the EDT, call invokeLater(). If you are in an Event Listener method (i.e. already on the EDT), you don't need to call invokeLater().



来源:https://stackoverflow.com/questions/28677698/when-and-where-to-call-eventqueue-invokelater-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!