2

簡単にするために、ファイルをダウンロードするアプリケーションを想像してみてください。進行状況を表示する1つのラベルが付いたシンプルなGUIがあります。EDT違反を回避するために、すべての合法的な市民のように、私は1つのスレッド(メイン)でファイルをダウンロードし、別のスレッド(EDT)でGUIを更新します。したがって、これがpseudcodeの関連するチャンクです。

class Downloader {
    download() {
        progress.startDownload();
        while(hasMoreChunks()) {
            downloadChunk();
            progress.downloadedBytes(n);
        }
        progress.finishDownload();
    }
}

class ProgressDisplay extends JPanel {
    JLabel label;
    startDownload() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                label.setText("Download started");
            }
        });
    }
    downloadedBytes(int n) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                label.setText("Downloaded bytes: " + n);
            }
        });
    }
    finishDownload() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                label.setText("Download finished");
            }
        });
    }
}

Javaがクロージャをサポートしておらず、コードが非常に明確であるという事実が気に入っています。冗談はさておき、私は疑問に思っています...私はそれを間違っていますか?SwingUtilitiesすべての方法での匿名の実装などで、この醜い定型文をすべて排除することは可能Runnableですか?

私の場合はこれより少し複雑ですが、プロキシなどを実装してオーバーエンジニアリングしないようにしています。

4

5 に答える 5

2

そのタスクには特別なクラスがあります: SwingWorker. 別のスレッドでコードを実行し、作業の最後に UI を更新できます。

于 2011-06-02T14:51:46.383 に答える
1

他の場所に多くの冗長なコードを導入せずに定型コードを回避するためにできることはあまりありません。しかし、小さな抽象ヘルパークラスといくつかの変わったフォーマットを使用して、それを少し良くすることができます。

public abstract static class SwingTask implements Runnable
{
    public void start()
    {
         SwingUtilities.invokeLater( this );
    }
}

startDownload() {
    new SwingTask() { public void run() {
        label.setText("Download started");
    } }.start();
}

コードのフォーマットは、この1行のすべてのコードが基本的に興味のない定型コードであり、必要な他の場所に簡単かつ安全にコピーできることを強調することを目的としています。私たちはこのフォーマットスタイルをしばらく使用してきましたが、非常に便利であることがわかりました。

于 2011-06-02T15:17:50.440 に答える
0

のようなヘルパーメソッドを使用します。

 public void setLabelText(final JLabel label, final String text) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            label.setText(text);
        }
    });
 }
于 2011-06-02T14:49:50.493 に答える
0

数年前のプロジェクトでSpinを使用しました。

于 2011-06-02T14:58:28.900 に答える
0

生のアイデア:

public class ThreadSafeJLabel extends JLabel {

    @Override
    public void setText(final String text) {
        if (SwingUtilities.isEventDispatchThread()) {
            super.setText(text);
        } else {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    setText(text);
                }
            });
        }
    }

}

試したことはありませんがsetText()、EDT から呼び出されたときsuperに使用されると思います。ただし、他のスレッドが関与している場合、オーバーライドされた ( ThreadSafeJLabel.setText()) は後で、今回は EDT 内で呼び出されます。

于 2011-06-02T15:06:43.433 に答える