использовать поток для обновления содержимого jlabel - PullRequest
0 голосов
/ 11 января 2020

Я хочу использовать поток для изменения содержимого JLabel при нажатии одной кнопки. эта кнопка обработает один документ, который стоит много времени. Но когда я нажимаю кнопку, содержимое JLabel будет показано после обработки документа. Я хочу, чтобы это можно было показать немедленно.

вот код

public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        String command = e.getActionCommand();
        // Load button
        if (command.equals("Load")) {
            // set load to true
            load = true;
            // get text area name
            name = nameField.getText();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    loadState.setText("Loading document "+name+" . Please wait!");
                }           
            }).start();
            // load daffodils
            if (name.toLowerCase().equals("daffodils.txt")) {
                try {
                    loadText(tpPoem);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
}

любой может сказать мне, почему этот поток не работает.

Ответы [ 2 ]

1 голос
/ 11 января 2020

Swing в основном однопоточный, вызов методов из нескольких потоков может вызвать проблемы. Вы должны изменить свою метку в специальном потоке, называемом потоком отправки событий (EDT).

ActionListener.actionPerformed работает в этом потоке, поэтому вместо

new Thread(new Runnable() {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        loadState.setText("Loading document "+name+" . Please wait!");
    }           
}).start();

Вы можете написать:

loadState.setText("Loading document "+name+" . Please wait!");

Кажется, что ваша загрузка также выполняется на EDT:

if (name.toLowerCase().equals("daffodils.txt")) {
    try {
        loadText(tpPoem);
    } catch (IOException e1) {
        e1.printStackTrace();
    }
}

Если вы используете фоновый поток в этом методе, тогда все в порядке, в противном случае проверьте SwingWorker, Это для выполнения длинных задач в фоновом потоке. Если вы блокируете EDT с помощью долго выполняющейся задачи, метка не будет обновляться до тех пор, пока задача не будет завершена.

Если вы хотите обновить GUI из фонового потока, SwingWorker имеет методы для этого. Кроме того, вам может быть интересен этот вопрос: Когда и где вызывать метод EventQueue.invokeLater ()

0 голосов
/ 11 января 2020

Попробуйте это:

public interface IWorkerThreadCallback {

    void onSuccess(boolean result);

    void onError(@NonNull Throwable result);
}


public class WorkerThread implements Runnable {
    private IWorkerThreadCallback callback;

    public WorkerThread(@NonNull IWorkerThreadCallback callback){
        this.callback = callback;
    }

    @Override
    public void run() {
        try {

            // do long task on a background thread

            // return when task is success
            callback.onSuccess(true);
        }
        catch (Exception ex){
            // return when task is error
            callback.onError(ex.fillInStackTrace());
        }
    }
}

// вызов рабочего потока из основного потока

 new Thread(new WorkerThread(new IWorkerThreadCallback() {
     @Override
     public void onSuccess(boolean result) {
         // success result
     }

     @Override
     public void onError(@NonNull Throwable result) {
         // error result
     }
 })).start();
...