4

私はこれを何時間も試しました.. UI の JTextField を変更するスレッドがあり、UI を完全に破壊します。スレッド (スレッド A と呼びましょう) は、ActionListener によって生成されます。.setText() 関数呼び出しは、スレッド A によって作成された追加のスレッド (B) にあります。スレッド B は、SwingUtilitis.invokeAll() および/または SwingUtilities.invokeAndWait() のパラメーターです。両方試してみました。より明確にするためのコードを次に示します。

これは、スレッド A を作成する私の ActionListener です - もちろん短縮されています:

public void actionPerformed(ActionEvent evt) {
    Object source = evt.getSource();
    if (source == window.getBtn_Search()) {
        Refresher refresh = new Refresher();
        refresh.start();
    }
}

これは私のスレッド A で、後でスレッド B を EDT キューに入れます。

public class Refresher extends Thread implements Runnable {

private int counter = 0;
private UI window = null;
private int defRefresh = 0;

@Override
public void run() {
    while(true){
        -bazillion lines of code-
                do {
                    try {
                        Refresher.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(window.canceled()) break;
                    UI.updateCounter(window.getLbl_Status(), (Configuration.getRefreshTime()-counter));
                    counter++;
                } while (counter <= Configuration.getRefreshTime());
             - more code-
    }
}
}

UI.updateCounter(...) はスレッド B を EDT のキューに入れます。

public static void updateCounter(final JLabel label, final int i) {
    try {
        SwingUtilities.invokeAndWait( 
            new Runnable() {
                public void run() {
                    label.setText("Refreshing in: " + i + " seconds.");
                }
            }
        );
    } catch (InvocationTargetException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

最後の関数が呼び出されると、すべてが台無しになります。私は何時間も別のものを試しましたが、何もうまくいきませんでした。SwingWorker も使用してみましたが、一部またはまったく発生しませんでした。

4

4 に答える 4

1

試行された は、実行可能なタスクを EDT で実行するように投稿するinvokeAndWait()ことを許可しますが、現在のスレッドをブロックし、EDT がタスクの実行を完了するまで待機します。

ただし、スレッドの相互依存関係を作成するコードにはデッドロックが発生する可能性があるため、invokeAndWait() にはデッドロックの可能性があります。呼び出し元のコードが、invokeAndWait() を介して呼び出されたコードが必要とする何らかのロックを (明示的または暗黙的に) 保持している場合、EDT コードは非 EDT コードがロックを解放するのを待ちますが、これは非 EDT コードが待機しているため発生しません。 EDT コードが完了すると、アプリケーションがハングします。

ここでわかるように、待機中の非 EDT コードによって渡された JLabel コンポーネントを変更します。

代わりに使用できます

invokeLater()Runnable を含む特別なイベントの作成とキューイングを処理します。このイベントは、他のイベントと同様に、受信した順序で EDT で処理されます。その時が来ると、Runnable の run() メソッドを実行することによってディスパッチされます。

SwingUtilities.invokeLater(new Runnable() {
public void run() {
label.setText("Refreshing in: " + i + " seconds.");
}
});

また

isEventDispatchThread()呼び出し元のコードが現在 EDT で実行されている場合は true、それ以外の場合は false を返します。

Runnable code= new Runnable() {
                public void run() {
                    label.setText("Refreshing in: " + i + " seconds.");
                }
            }
        );

if (SwingUtilities.isEventDispatchThread()) {
code.run();
} else {
SwingUtilities.invokeLater(code);
}
于 2016-03-21T19:45:56.543 に答える
0

一般に、ラベルは変化するテキストを表示するのが得意ではありません: 幅の変化とそれに伴うレイアウト。

おそらくスタイルを適切に変更して、読み取り専用の JTextField を使用すると、より良い解決策になる可能性があります。

于 2014-05-14T20:31:10.913 に答える
0

JPanelあなたが作成した中間体は検証ルートとしてカウントされると思います。したがって、revalidate()呼び出し時に自動的に発生するは、親setText()のレベルよりも高いレイアウトの変更を引き起こしません。JPanel

JLabelにはアイコンとテキストの両方を含めることができるため、実際にはパネルは必要ないと思います。チュートリアルを参照してください。

したがって、私のアドバイスは、パネルを削除するか、目的にかなう場合はisValidateRoot()、パネルで false が返されるようにすることです。

于 2014-05-22T05:44:25.587 に答える
-1

のテキストを変更するときlabelは、少なくともの最上位のコンテナを呼び出しrepaint()/revalidate()label、再レイアウトをトリガーする必要があります。label呼び出しがinvalidate()/revalidate()テキストの変更で正しく行われたと仮定します。

于 2013-01-04T22:09:41.650 に答える