5

私の質問は理論に基づいた質問ですが、私が持っている特定のニーズを満たしています。

SwingWorker が a) 予期できる例外をスローし、b) 回復して続行する必要があるが、このエラーが発生したことをユーザーに通知したい場合はどうしますか? doInBackground()「No Swing code from 」ルールに違反することなく、予想される例外を取得してユーザーに通知するにはどうすればよいですか?

この問題を考慮して、私は SSCCE を作成し、その下に質問を提示したいと思います。

SSCCE:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Test {

    public static void main(String args[]) {
        final JFrame frame = new JFrame();
        JButton go = new JButton("Go.");
        go.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Task(frame);
            }
        });
        frame.add(go);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    static class Task extends SwingWorker<Void, Void> {
        JFrame parent;
        JDialog dialog;
        public Task(JFrame parent) {
            this.parent = parent;
            dialog = new JDialog(parent);
            JProgressBar jpb = new JProgressBar();
            jpb.setIndeterminate(true);
            dialog.add(jpb);
            dialog.setLocationRelativeTo(null);
            dialog.setVisible(true);
            execute();
        }

        @Override
        protected Void doInBackground() throws Exception {
            for(int i = 0; i < 100000; i++) {
                System.out.println(i);
                try {
                    if(i == 68456) throw new IllegalStateException("Yikes! i = 68456.");
                } catch (final IllegalStateException e) {
                    SwingUtilities.invokeAndWait(new Runnable() {
                        @Override
                        public void run() {
                            JOptionPane.showMessageDialog(parent, "Error: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                        }
                    });
                }
            }
            return null;
        }

        @Override
        protected void done() {
            if (!isCancelled()) {
                try {
                    get();
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("done");
            dialog.dispose();
        }

    }
}

メソッドSwingUtilities.invokeAndWait()内で呼び出すことは有効ですか? doInBackground()これについてスレッドのプロファイリングを行ったところ、結果は次のようになりました。

ここに画像の説明を入力

「Go」ボタンが押されると、SwingWorker-pool-1-thread-1スレッドは緑色になります。THEN、if 条件が満たされると、エラーがスローされ、エラー ダイアログが表示され、スレッドが黄色AWT-EventQueue-0になり、EDT が呼び出されたことを示す緑色の「ブリップ」がスレッドに表示されます。約 10 秒待って「OK」を押すと、SwingWorkerスレッドが再び緑色になりました。

このようなことをすることの潜在的な落とし穴はありますか? からリアルタイムで計算エラーをユーザーに通知した経験のある人はいSwingWorkerますか?

正直なところ、このアプローチには不安があります。異例のようですが、これが悪い考えかどうかは断言できません。

4

1 に答える 1

4

invokeAndWait()ユーザーが実際に承認する必要がある場合に使用しても問題はありません。そうでない場合は、このに示すように、SwingWorker<Void, String>単にpublish()データとエラー メッセージを交互に呼び出して呼び出すことができます。追加された適切なメッセージdone()により、ユーザーは必要に応じて蓄積された出力を確認できます。

于 2013-12-14T01:08:51.547 に答える