Java JFrame: обновление графического интерфейса во время события (не по таймеру)

Пытался сделать это некоторое время, но не быстро. У меня есть элементы в JFrame, которые я хочу обновить/переключить жизнеспособность, когда я нажимаю кнопку воспроизведения (которая запускает ActionEvent). Однако кажется, что они обновляются только после завершения метода actionPerformed. Это то, что я думаю, происходит, потому что конструктор для моего объекта SoundPlayer запускает (Thread.sleep), вызывая заметную задержку. Я прочитал здесь, что использование Thread.sleep() блокирует графический интерфейс, но я вношу свои изменения перед вызовом SoundPlayer, поэтому не думаю, что это будет проблемой.

Как показано ниже, я попытался перерисовать JFrame в целом, а также отдельный элемент. Они не обновляются до тех пор, пока не завершится задержка SoundPlayer, хотя мой оператор println печатает правильное время.

Многопоточность пришла мне в голову как решение, хотя я не понимаю, зачем мне это нужно. Любая помощь в этом вопросе приветствуется!

public void actionPerformed(ActionEvent e){

    int channel = 0, volume = 0;    //Assigned for safety.
    String musicNotes = "";   //Will be filled with the under-input.
    boolean willPlay = true;    //Assumes will be played.

    /*Stuff that makes 'willPlay' either true of false*/

    //If nothing is wrong, plays the String!
    if (willPlay) {       //If above parameters are good...
        badNums.setVisible(false);
        prog.setVisible(true);

        if (vis.isSelected())
            prog.setText("Estimated duration: " + estiDuration(musicNotes)*(0.4) + "seconds");
        else
            prog.setText("Duration: " + estiDuration(musicNotes)*(0.3) + "seconds");

        System.out.println("test");
        repaint();
        prog.repaint();

        new SoundPlayer(channel, volume, musicNotes);          //Plays the music!
    } else {
        vis.setVisible(false);
        badNums.setVisible(true);
    }
}

person Ryan Stevens    schedule 05.06.2015    source источник


Ответы (1)


Swing является однопоточным — весь код для рисования, событий и т. д. выполняется в этом потоке (называемом EDT). Если у вас есть длительно выполняемая задача и вы помещаете ее в EDT, она не может ничего делать, пока не будет завершена (обратите внимание, что вызов repaint не вызывает напрямую repaint Component, поэтому запуск чего-то длительного после этого вызова не означает, что Component на самом деле красить себя перед). Если вам нужно выполнять длительные операции, делайте это в другом Thread — это можно сделать либо непосредственно с помощью Thread или с помощью SwingWorker. Если первое, убедитесь, что любые вызовы Swing отправляются в EDT с использованием SwingUtilities.invokeXXX

person copeg    schedule 05.06.2015
comment
Большое спасибо. После попытки включить SwingWorker я вернулся к Thread, который я знаю, и он работал как шарм без особого дополнительного редактирования! Теперь я должен быть в состоянии вернуться к своей первоначальной цели обновления прогресса моей обработки String во время воспроизведения звука! - person Ryan Stevens; 06.06.2015