Search code examples
javamultithreadingswing

Must JTextField.getText and JButton.addActionListener be Executed on the EDT


Should I assume that the following program is wrong because lines x and y (at the very end of the main method) are not executed on the EDT?

public class Temp
{
    private static JButton     button;
    private static JTextField  text;
    
    private static void showGUI()
    {
        JFrame  frame       = new JFrame();
        JPanel  contentPane = new JPanel();
        button = new JButton( "Push Me" );
        text = new JTextField( "I am the walrus" );
        contentPane.add( button );
        contentPane.add( text );
        frame.setContentPane( contentPane );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
        throws InterruptedException, InvocationTargetException
    {
        SwingUtilities.invokeAndWait( () -> showGUI() );
        /* x */ System.out.println( text.getText() );
        /* y */ button.addActionListener( System.out::println );
    }
}

Solution

  • Yes, you should.

    Lines x and y are indeed not executed on the EDT, which could lead to potential issues in Swing applications.

    The SwingUtilities.invokeAndWait() method you're using in the main method is used to execute the showGUI() method on the EDT, which is correct. However, the subsequent lines x and y are executed on the main thread, which could lead to synchronization problems and unexpected behavior.

    To ensure that lines x and y are executed on the EDT, you should wrap them in a SwingUtilities.invokeLater() call as well.

    This way:

    public static void main(String[] args)
        throws InterruptedException, InvocationTargetException
    {
        SwingUtilities.invokeAndWait( () -> showGUI() );
        
        SwingUtilities.invokeLater( () -> {
            /* x */ System.out.println( text.getText() );
            /* y */ button.addActionListener( System.out::println );
        });
    }
    

    Check this out