Swing implements page updates through background threads

Business scene

In the swing program, we want to implement a function that updates the component synchronously as the task is executed. If the task is directly executed and the component is updated in the main thread (EDT), it will cause the component to only display the final updated status. This This is because EDT is single-threaded, which will cause the thread to be blocked when performing time-consuming tasks, and the swing component cannot be updated immediately.

In order to realize this function, we need to use a background thread to execute the task, and then synchronize it to the EDT thread after execution. For specific implementation, we can use the SwingWorker function to implement real-time updates of components while executing background tasks.

related functions

Below we introduce several important functions in SwingWorker:

  1. doInBackground() method :

    • doInBackground()is SwingWorkerone of the most important methods in .
    • In this method, you can perform time-consuming tasks such as file downloads, data processing or calculations, etc.
    • This method runs on a background thread and does not block the event dispatch thread (EDT), thus ensuring the responsiveness of the user interface.
  2. publish() and process() methods :

    • publish(V... chunks)Method used to publish chunks of data to the event dispatch thread (EDT) for processing.
    • process(List<V> chunks)Method for processing published chunks of data on the event distribution thread (EDT).
    • This pair of methods work together to allow you to send data to the event dispatch thread during the execution of a background task to update Swing components such as progress bars or text labels in real time on the user interface.
  3. done() method :

    • done()Methods are executed on the event dispatch thread (EDT) after the background task completes.
    • You can handle any finishing work after the task is completed in this method, such as cleaning up resources, displaying results, or triggering other actions.
  4. get() method :

    • get()Method is used to obtain the results of the background task.
    • It can be used to retrieve results after a task is completed, but be aware that calling get()the method blocks the current thread until the task is completed.
  5. cancel() method :

    • cancel(boolean mayInterruptIfRunning)Method used to cancel background tasks.
    • If mayInterruptIfRunningthe argument is true, an attempt will be made to interrupt the running task. Otherwise, it will attempt to cancel the task but will not interrupt running tasks.

Here we need to note that SwingWorker declares a data block chunk generic array to realize data interaction between the background process and the EDT main process.

In our case code below, doInBackground() will update the chunk array through publish each time after simulating a time-consuming operation, and get the last bit of data in the array in the procedures function to achieve real-time updates.

Case code

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class test {
    private JFrame frame;
    private JProgressBar progressBar;
    private JLabel progressLabel;

    public test() {
        frame = new JFrame("Progress Bar Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 100);
        frame.setLayout(new FlowLayout());

        progressBar = new JProgressBar(0, 100);
        progressBar.setStringPainted(true); // 显示百分比
        frame.add(progressBar);

        progressLabel = new JLabel("Progress: 0%");
        frame.add(progressLabel);

        JButton startButton = new JButton("Start");
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startTask();
            }
        });
        frame.add(startButton);

        frame.setVisible(true);
    }

    private void startTask() {
        SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
            @Override
            protected Void doInBackground() throws Exception {
                for (int i = 0; i <= 100; i++) {
                    Thread.sleep(100); // 模拟耗时任务
                    publish(i); // 发布进度
                }
                return null;
            }

            @Override
            protected void process(java.util.List<Integer> chunks) {
                int latestProgress = chunks.get(chunks.size() - 1);
                progressBar.setValue(latestProgress);
                progressLabel.setText("Progress: " + latestProgress + "%");
            }

            @Override
            protected void done() {
                progressLabel.setText("Progress: 100% (Task completed)");
            }
        };

        worker.execute(); // 启动后台任务
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new test();
            }
        });
    }
}

renderings

Guess you like

Origin blog.csdn.net/qq_51118755/article/details/133201561