-1

編集:私のコードを簡素化しました。

これは、GUI およびサーバー スレッドを初期化するメイン クラスです。

public class Main {
    public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, UnknownHostException {
    Runnable tGUI = new TransceiverGUI();
    Runnable server = new Server(tGUI);
    new Thread(tGUI).start();
    new Thread(server).start();
    }
}

現在、私のpublic class TransceiverGUI extends javax.swing.JFrame implements Runnableクラスには、次のメソッドがあります。

protected boolean incomingFileRequest(String filename, long filesize, String user) throws InterruptedException, InvocationTargetException {
        /* .... code logic which executes .... */
        /* UPDATE GUI HERE DOES NOT WORK */
        LabelProgress.setForeground(Color.red);
        LabelProgress.setText("Receive Progress");
    }

GUI クラス内から (任意の EventListener から) 呼び出されるたびincomingFileRequestに、完全に機能し、GUI が更新されます。

incomingFileRequestただし、クラス/スレッドから呼び出すとServer、コードが実行されて正しい値が返されますが、GUI は更新されません。

サーバー スレッドは次のように呼び出します。 // POPUP with request boolean answer = gui.incomingFileRequest(message.getMessage(), message.getFileSize(), message.senderIPAddress);

GUI を更新するコードを、次のような新しいスレッドを作成するブロックに配置しました。

Thread t = new Thread() {
public void run() {
   LabelProgress.setForeground(Color.red);
   LabelProgress.setText("Receive Progress");
   repaint();
}
};
t.start();

私も試しjavax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { /* update GUI code */ } });ました。

私の質問は、別のスレッドから GUI クラス内のメソッド (GUI を更新する) を呼び出すにはどうすればよいですか? コードが完全に実行されることに注意してください。GUI 要素は更新されません。

どんな助けでも大歓迎です。

4

2 に答える 2

2

あなたの投稿から

IncomingFileRequest が GUI クラス内から (任意の EventListener から) 呼び出されるたびに、完全に機能し、GUI が更新されます。

ただし、サーバー クラス/スレッドから incomingFileRequest を呼び出すと、コードが実行されて正しい値が返されますが、GUI は更新されません。

それはまさに、一部の人々がコメントであなたに説明しようとしたことです. すべての GUI 更新は、GUI スレッド - EDT で実行する必要があります。

イベントディスパッチスレッドは、GUI が更新される理由である「リスナー」を処理するスレッドです。別のスレッドから GUI を更新するには、変更が EDT で実行されるように「スケジュール」するだけです。これを行うには、GUI 変更コードをクラスにラップし、メソッドRunnableを介して EDT に渡します。SwingUtilities.invokeLalater(Runnable)このようにして、GUIはできるだけ早く更新されます

あなたはそれにも言及しました

javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { /* GUI コードの更新 */ } }); も試しました。

で、結果は?これはまさにそれが行われるべき方法だからです。これがうまくいかない場合は、メソッド本体が外部の更新を待っているか、あなたが思っているよりも別のタイミングでスケジュールされているかのいずれかで、コードに別の問題があります。

于 2015-08-16T15:41:28.430 に答える
0

最初は持っていた

public class Main {

    public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, UnknownHostException {

    Runnable tGUI = new TransceiverGUI();
    Runnable server = new Server(tGUI);

    System.out.println("Starting GUI...");
    new Thread(tGUI).start();
    System.out.println("Starting Server...");
    new Thread(server).start();
    }
}

何時間も解決策を探した後、パラメーターをスレッドに渡す方法を逆にしただけです。次の (動作する) コードでわかるように、まずサーバー スレッドを作成し、それをパラメーターとして GUI スレッドに渡します。また、それに応じてパラメーターを受け入れるように、対応するコンストラクターを変更しました。

変更後、すべてが完全に機能しました。この変更が私の問題を解決した理由は実際にはありません。

public class Main {

        public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, UnknownHostException {

        Runnable server = new Server();
        Runnable tGUI = new TransceiverGUI(server);

        System.out.println("Starting Server...");
        new Thread(server).start();
        System.out.println("Starting GUI...");
        new Thread(tGUI).start();
        }
    }
于 2015-08-28T18:19:21.520 に答える