1

この質問のために書いた例では問題を再現できなかったため、これは少し難しいと思います(以下の例は完全に機能します)。実際のアプリケーションで起こりうる問題について、誰かが手がかりを持っていることを願っています。いくつかの長いテキスト操作を実行するアプリを作成しました。各操作は、独自のスレッドで実行されます。ユーザーがすべての進行状況を確認できるように、スレッドによって更新される Frame があります。

問題は、すべてのスレッドがジョブを完了した後にのみ、送信されたすべての更新とともにフレームが表示されることです。
アプリ全体を以下のコードに単純化しましたが、問題はここで機能することです。どんなアイデアでも大歓迎です。

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

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Main {

    private MyFrame frame;
    private ExecutorService executorService;

    public static void main(String[] args) throws InterruptedException {
        Main main = new Main();
        main.startProcess();
    }

    public void startProcess() throws InterruptedException {
        // Initialize the frame
        frame = new MyFrame();
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                frame.setVisible(true);
            }
        });

        // Initialize executorService for 3 threads and also 6 runnables
        executorService = Executors.newFixedThreadPool(3);
        MyRunnable runnable;
        for(int i = 0; i < 6; i++) {
            runnable = new MyRunnable(this, i);
            executorService.execute(runnable);
        }

        // Start runnables
        executorService.shutdown();

        // Wait until all runnables are executed
        while (!executorService.isTerminated()) {
            Thread.sleep(10000);
        }

        // When all runnables are done close the frame
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                frame.setVisible(false);
            }
        });
    }

    // Update the frame display
    public synchronized void updateDisplay(final String update) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                frame.updateDisplay(update);
            }
        });
    }

    private class MyFrame extends JFrame {
        private JPanel contentPane;
        private JLabel lblDisplay;

        public MyFrame() {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            contentPane = new JPanel();
            contentPane.setLayout(new BorderLayout(0, 0));
            setContentPane(contentPane);

            lblDisplay = new JLabel("Display");
            contentPane.add(lblDisplay, BorderLayout.CENTER);

            pack();
        }

        public void updateDisplay(String update) {
            lblDisplay.setText(update);
            pack();
        }
    }

    private class MyRunnable implements Runnable {
        private int id;
        private Main main;

        public MyRunnable (Main main, int id) {
            this.main = main;
            this.id = id;
        }

        @Override
        public void run() {
            for(int i = 0; i < 3; i++) {
                main.updateDisplay("Runnable " + id + " stepped " + i + " times.");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
4

1 に答える 1

3

SwingWorkerのジョブと 1 つの JFrame のみ。例はこちら

から GUI への出力は、ここでRunnable#Threadにラップする必要がありますinvokeLater()

またはExecutor から SwingWorker を呼び出す

于 2011-11-07T15:59:54.987 に答える