Java Swing Threading с обновляемым JProgressBar - PullRequest
2 голосов
/ 02 марта 2011

Во-первых, в последнее время я довольно много работал с пакетом параллелизма Java, но обнаружил проблему, на которой я застрял.Я хочу, чтобы и Приложение, и Приложение могли иметь SplashScreen со строкой состояния и загрузкой других данных.Поэтому я решил использовать SwingUtilities.invokeAndWait( call the splash component here ).Затем появляется SplashScreen с JProgressBar и запускается группа потоков.Но я не могу понять, как с этим справляться.Я просмотрел SwingWorker и попытался использовать его для этой цели, но поток просто возвращается.Вот немного псевдокода.и очки, которые я пытаюсь достичь.

  • Есть приложение с SplashScreen, которое останавливается при загрузке информации
  • Возможность запуска нескольких потоков под SplashScreen
  • Индикатор выполнения функции SplashScreen с возможностью обновления еще не завершается, пока не завершены все потоки.

Запуск заставки

try {
    SwingUtilities.invokeAndWait( SplashScreen );
} catch (InterruptedException e) {
} catch (InvocationTargetException e) { }

Всплывающее окноконструкция

SplashScreen extends JFrame implements Runnable{

    public void run() {
        //run threads
        //while updating status bar
    }
}

Я пробовал много вещей, включая SwingWorkers, потоки с использованием CountDownLatch и другие.CountDownLatch на самом деле работал так, как я хотел сделать, но я не смог обновить графический интерфейс.При использовании SwingWorkers либо invokeAndWait был в основном аннулирован (что и является их целью), либо он не обновлял бы графический интерфейс, даже если использовался PropertyChangedListener.Если у кого-то есть пара идей, было бы здорово услышать их.Заранее спасибо.

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

Ответы [ 2 ]

5 голосов
/ 02 марта 2011

Для выполнения ряда операций в фоновом режиме и создания отчетов о ходе выполнения используйте SwingWorker .

Метод background выполняет фоновую обработку.
Используйте метод publish для публикации периодических обновлений статуса.
Переопределите метод process для обработки обновлений (process всегда выполняется в EDT).

progressBar = new JProgressBar();
sw = new SwingWorker<Boolean,Integer>() {
    protected Boolean doInBackground() throws Exception {
        // If any of the operations fail, return false to notify done() 
        // Do thing 1
        publish(25);  // 25% done
        // Do thing 2
        publish(50);  // 50% done
        // Do thing 3
        publish(75);  // 75% done
        // Do thing 4
        return true;
    }
    protected void process(List<Integer> chunks) {
        for (Integer i : chunks)
            progressBar.setValue(i);
    }
    protected void done() {
        try {
            boolean b = get();
            if (b)
                progressBar.setValue(100); // 100% done
            else
                // Notify the user processing failed
        }
        catch (InterruptedException ex) {
                // Notify the user processing was interrupted
        }
        catch (ExecutionException ex) {
                // Notify the user processing raised an exception
        }
    }
};

Добавление:

Это можно распространить на несколько задач, просто нужно изменить подход к настройке индикатора выполнения. Вот что приходит на ум:

Иметь массив счетчиков завершения, по одному на задачу.

int[] completions = new int[numTasks];
Arrays.fill(completions,0);

Запустите SwingWorkers, каждому из которых был присвоен индексный номер. Затем методы process или done вызывают что-то вроде этого, чтобы обновить общий индикатор выполнения.

void update(int index, int percComplete) {
    completions[index] = percComplete;
    int total = 0;
    for(int comp: completions)
        total += comp/numTasks;
    overallPB.setValue(total);
}

При желании можно отобразить JProgressBar для каждой задачи.

Приложение 2:

Если задачи различаются по времени выполнения (например, попадание в кэш или пропуск в кэш), вы можете исследовать ProgressMonitor . Это диалоговое окно хода выполнения, которое отображается только в том случае, если задача занимает больше времени (настраивается, по умолчанию 500 мс).

0 голосов
/ 02 марта 2011

Нет необходимости вызывать фрейм внутри invokeAndWait, но вы должны обновить состояние индикатора выполнения следующим образом.

try {
   SwingUtilities.invokeAndWait( new Runnable() {
     public void run() {
//update state of the progress bar here
     }
   });
 } catch (InterruptedException e) {
 } catch (InvocationTargetException e) { }
...