2017-11-07 16 views
0

実際は私はJavaスレッドの初心者です。私の学習目的のために、私は簡単なプログラムを作成しました。私はどこに行かなかったのか分からない。javafxのスレッドで自動的にラベルが更新されない

コード:

package javaguithread; 

import javafx.fxml.FXML; 
import javafx.scene.control.Label; 
import javafx.scene.control.TextField; 

public class Controller { 

    Thread t1; 

    @FXML 
    TextField input; 

    @FXML 
    Label output; 

    @FXML 
    private void addData() { 
     output.setText(input.getText()); 
    } 

    public void initialize() { 

     t1 = new Thread(() -> { 

      while (true) { 
       System.out.println(input.getText()); 
       output.setText(input.getText()); 
      } 
     }); 

     t1.start(); 
    } 
} 

それが示すエラーが

at com.sun.javafx.tk.Toolkit.checkFxUserThread(
Toolkit.java:236) 

を更新している私は、私が作成した別のクラスでスレッドを初期化しようとしました。彼女は私のコードです。

package javathreadgui; 

import javafx.application.Platform; 
import javafx.concurrent.Task; 
import javafx.fxml.FXML; 
import javafx.scene.control.Label; 
import javafx.scene.control.TextField; 

public class Controller { 

    private class GuiUpdater extends Task<Void> { 

     Controller ctrl; 

     GuiUpdater(Controller ctrl) { 
      this.ctrl = ctrl; 
     } 

     @Override 
     protected Void call() throws Exception { 
      makeChanges(); 
      return null; 
     } 

     private void makeChanges(){ 
     while(true){ 
      Platform.runLater(() -> { 
       ctrl.output.setText(ctrl.input.getText()); 
      }); 

      System.out.println("test"); 

     } 
     } 

    } 

    @FXML 
    TextField input; 

    @FXML 
    Label output; 

    public void initialize() { 
     System.out.println("Hello "); 

     Task<Void> task = new GuiUpdater(this); 

     Thread thread = new Thread(task); 

     thread.setDaemon(true); 
     thread.start(); 
    } 

} 

私は他の

System.out.println("test"); 

GUIがフリーズとしてコンソール出力を作るとき、それはpreetyうまく動作します。私はそれのために何をすることができますか?

+0

を使用する唯一の誤りのフルエラーログ –

+0

を投稿してください。 –

+0

なぜコントローラーの初期化時に新しいスレッドの下で出力ラベルのテキストを設定するのですか? –

答えて

3

JavaFXスレッドでUIを変更する必要があります。あなたのsetTextラップ()以下のコードを呼び出す:

Platform.runLater(new Runnable() { 
     @Override public void run() { 
      output.setText(input.getText()); 
     } 
}); 

あなたが並行性とどのようにタスク/スレッドを通じてUIを更新することができますについて検索することができますポストのトンがあります。しかし、あなたが知る必要があるすべての詳細を掘り下げたいのであれば、すべてのUI更新がすべてPlatform.runLater(...)呼び出しの中になければならないということです。

編集:ここでは

はあなたを助けるかもしれない例です。

import java.util.Scanner; 
import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.concurrent.Task; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.stage.Stage; 

public class LabelUpdateTest extends Application { 

    private Label label; 

    @Override 
    public void start(Stage stage) throws Exception { 
     label = new Label("Waiting for input.."); 
     stage.setScene(new Scene(label, 100, 100)); 
     stage.show(); 

     initInputThread(); 
    } 

    private void initInputThread() { 

     Scanner input = new Scanner(System.in); 

     Task<Void> task = new Task<Void>() { 
      @Override 
      protected Void call() { 
       while (true) { 
        String userInput = input.nextLine(); 

        Platform.runLater(new Runnable() { 
         @Override 
         public void run() { 
          label.setText("Input was : " + userInput); 
         } 
        }); 

       } 
      } 
     }; 

     Thread th = new Thread(task); 
     th.setDaemon(true); 
     th.start(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

ありがとう@JKostikiadis私は確かにそれをつかむでしょう。 :) –

+0

私は最終的なAtomicInteger数=新しいAtomicInteger(-1)に手がかりを得ることができますか? –

+0

さて、私はここでいくつかの素晴らしい投稿を読むことをお勧めします:https://stackoverflow.com/questions/4818699/practical-uses-for-atomicinteger しかし、あなたは単に非javaFXスレッドを通してあなたのUIを更新したいと思っていませんそれは、Platform.runLater内でUIの更新を呼び出すだけです – JKostikiadis

1

ちょうど

Platform.runLater(() -> { 
    output.setText(input.getText()); 
} 
関連する問題