Search code examples
javaswingevent-dispatch-thread

Does actionPerformed(ActionEvent e) runs in a different thread than the Event Dispatch Thread (EDT)?


Does actionPerformed(ActionEvent e) runs in a different thread than the Event Dispatch Thread (EDT)? Say I wrote the following code:

public void main(String args[]){
     EventQueue.invokeLater(new Runnable() {
        public void run() {
            try { 
                  Frame f = new Frame();
                  f.setVisible(true);
                  javax.swing.SwingUtilities.isEventDispatchThread()
                }
            catch(Exception e){ e.printStackTree;}
}

public Frame()
{ //...some code....

    JButton btn = new JButton();
    //int a;
    javax.swing.SwingUtilities.isEventDispatchThread()
    btn.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) { 
            //..some code....
            javax.swing.SwingUtilities.isEventDispatchThread()
            //a++;
        }
    }
}

Though running javax.swing.SwingUtilities.isEventDispatchThread() returnd true in all three cases, it sill is impossible to do a++ inside actionPreformed.

I debugged this project, and correct me if I'm wrong: all though the entire frame is running from within the EDT, the EDT initiated new different threads for the Frame() constructor, and for the actionPreformed() function. Then, because of that, in order to escape the possibility of actionPreformed() will use the variable a that was created in another thread that could end before the actionPreformed()'s thread, its not possible to have a as a regular ''int'', only ''final int'' is permitted.

1 So does the actionPrefromed() function in this example runs in a different thread than the Frame() constructor's thread?

1.1 If not, then why isn't possible to modify a in the actionPreformed() funcion?

1.2 If yes, then how could I store values that could be kept in the Frame() constructor? or could at least be accessed by other different buttons?

2 Why create the frame f, or setting it to visible should be done inside the ETD in the first place?


Solution

  • The issue isn't threading, it's that the anonymous ActionListener class is just that - a different class. The lifetime of the ActionListener is longer than the lifetime of the local variable 'a', so you can't modify it. Hence, it has to be final.

    It actually makes absolutely no sense for you to try to 'keep a variable in the constructor', and then allow a longer-lived class to modify it.

    I believe that the closest thing to what you want is to make 'a' a member variable of the Frame class. You can then access it in your ActionListener with "Frame.this.a" if you must, but a public method in Frame would be a better idea.

    Finally, creating the frame and setting it to "visible" is done on the EDT because that's the only thread where it's safe to modify a Swing component.