smftr
smftr

Reputation: 955

Why do my changes in ActionListener not take effect immediately?

This is my code:

public MyClass() {
    JButton btnNext;
    private void initComponents() {
        btnNext = new javax.swing.JButton();
        btnNext.setText("Lanjut");
        btnNext.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnNextActionPerformed(evt);
            }
        });
    }

    private void btnNextActionPerformed(java.awt.event.ActionEvent evt) {
        btnNext.setText("Loading...");
        callingFunction();
    }
}

Note: callingFunction() is a function which takes a long time to execute.

My problem is my button text will change to "Loading..." only after callingFunction() is done.

How do I change the btnNext text to "Loading..." immediately?

Upvotes: 0

Views: 90

Answers (1)

Boann
Boann

Reputation: 50041

The button won't be repainted until control returns to the Swing event queue. Calling that function on the event dispatch thread is blocking the event queue.

As a workaround, tell it to run the function later (as soon as it's done repainting things):

In Java 8+:

EventQueue.invokeLater(() -> callingFunction());

In old Java:

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        callingFunction();
    }
});

Note that this will still have the side-effect of blocking further interaction with the GUI while that function is running. If you want to run a long task in a background thread to keep the GUI interactive, use a SwingWorker. A minimal example, assuming callingFunction returns some result of type String (or whatever) that you want to use to update the display:

new SwingWorker<String,Void>() {
    @Override
    protected String doInBackground() throws Exception {
        // called on a background thread
        return callingFunction();
    }

    @Override
    protected void done() {
        // called on the event dispatch thread after the work is done
        String result;
        try {
            result = get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // do something with the result ...
        someTextField.setText(result);
    }
}.execute();

Upvotes: 5

Related Questions