Показать/обновить компоненты до завершения процесса

В настоящее время у меня есть java-программа с графическим интерфейсом Swing, которая позволяет пользователю выбирать различные файлы (xsl-fo и xml) и создавать PDF-файлы с использованием Render X. Некоторое время я пытался заставить всплывающее окно JFrame появляться при нажатии кнопки, который затем будет отображать индикатор выполнения или метку, чтобы информировать пользователя о ходе выполнения. Однако при создании нового кадра он будет отображаться черным или без компонентов, которые затем отобразятся после завершения процессов.

private void RunButtonActionPerformed(java.awt.event.ActionEvent evt) {

    ExecutorService executor = Executors.newFixedThreadPool(8);

    //for reach file to process)
    for (int i = 0; i < count; i++) {
        Runnable worker = new ProcessThreader(conf, i);
        executor.execute(worker);
    }

    executor.shutdown();
    JFrame PercentageFrame = new JFrame();
    PercentageFrame.setVisible(true);
    PercentageFrame.setSize(200, 200);
    PercentageFrame.repaint();

    while (!executor.isTerminated()) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            NarrowOptionPane.errorMessage("Interrupted: ", ex.getMessage());
        }
    }
    System.out.println("Complete");
}

Кнопка запуска расположена в JPanel, которая находится в JFrame, а экземпляр основного фрейма создается в основном методе и заворачивается в метод вызова позже.

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            JFrame frame = new MainFrame("PDF Producer");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
            frame.setSize(710, 530);
            frame.setResizable(false);
            frame.setLocationRelativeTo(null);
        }
    });
}

Я новичок в многопоточности/исполнителях и Java-свинге, так что полегче! Спасибо


person iswinky    schedule 06.12.2013    source источник
comment
удалите цикл while, это должно вам помочь, также обновите свой PercentageFrame с ProcessThreader.   -  person alex2410    schedule 06.12.2013


Ответы (2)


Ваш while блок цикла EDT, удалите его, и ваш код будет работать.

См. следующий пример с ExecutorService и JProgressBar :

import java.awt.BorderLayout;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JFrame;
import javax.swing.JProgressBar;

public class Example extends JFrame {

    private static JProgressBar progress;

    public static void main(String[] args) {
        final JFrame f = new JFrame();
        progress = new JProgressBar();
        progress.setStringPainted(true);
        progress.setIndeterminate(true);
        ExecutorService newCachedThreadPool = Executors.newFixedThreadPool(1);
        for( int i =0; i<10;i++){
            final int j = i;
            Runnable r = new Runnable() {

                @Override
                public void run() {
                    progress.setString(j+"");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            newCachedThreadPool.submit(r);
        }
        f.getContentPane().add(progress,BorderLayout.CENTER);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setVisible(true);
    }

}

Здесь JFrame показывает количество Runnable, выполненных в ExecutorService. Также, если вам нужно получить результат от ваших Runnables, попробуйте использовать Callable вместо Runnable. При этом, когда вы submit Callable вы получаете Future экземпляр, из которого вы можете получить результат.

Прочтите о Executors, Callable и Future.

person alex2410    schedule 06.12.2013
comment
Для справки, SwingWorker реализует Runnable, Future<T> и RunnableFuture<T>. - person trashgod; 06.12.2013

Код, выполняемый из слушателя, выполняется в потоке отправки событий. Таким образом, Thread.sleep() приводит к тому, что EDT переходит в спящий режим, что означает, что графический интерфейс не может реагировать на события или перерисовывать себя.

Прочтите раздел руководства Swing по Параллелизм в Swing, чтобы узнать больше. Информация. Одним из решений, описанных в руководстве, является использование SwingWorker для длительной задачи и публикация результатов по мере их появления.

person camickr    schedule 06.12.2013