2016-05-02 7 views
3

は、この質問は、すでに尋ねているが、私はそれをudnerstand copuldnt。想像してみろ。私は2つのシーンを持つプログラムを持っています。データベースへの接続のためのシーンである第1のシーン1が開かれる。 Statusと呼ばれるラベルがあり、接続が確立されると([接続ボタン]をクリックして)「切断」から「接続済み」に変わる必要があります。だから私はボタンを "Connect" onClickイベントを取る関数を作った。この関数は、コントローラクラス内で宣言され、定義されています(私はfmxlをシーンビルダで設計しています)。だから基本的に私はコントローラクラスの内部にある接続関数(メソッド)からステータスを "接続済み"(status.setText( "Connected"))に変更したいと思っています。しかし、私はそれを行う際に、接続が確立された後、テキストは瞬時に変更されていませんが、シーンがクローズしようとしていると私は新しいものにシーンを変更しようとしていたとき、それは変更さ...私はインターネット上で読んで、私はPlatform.runLaterを使用する必要があることを見たので、私が試しスレッド:JavaFXの

private void changeSC() throws IOException, InterruptedException, SQLException 
{ 

    dbConnect(); 

    Thread thrd = new Thread() { 

     public void run() { 

       Platform.runLater(new Runnable() { 
        @Override public void run() { 
        status.setText("Connected"); 
         status.setTextFill(Color.GREEN); 
        }}); 
     } 
    }; 
    thrd.start(); 

    //pb.setProgress(1.0); 
    Parent root = FXMLLoader.load(getClass().getResource("Design.fxml")); 
    Scene primary = new Scene(root,1024,768); 
    primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 
    System.out.println("Text changing to COnnected"); 
    status.setTextFill(Color.GREEN); 
    Thread.sleep(2000); 
    Main.window.setScene(primary); 

} 

changeSCが接続]ボタンをクリックしたときに実行される関数です。これは私の古いバージョンでも動作しません:

private void changeSC() throws IOException, InterruptedException, SQLException 
{ 

    dbConnect(); 

     status.setText("Connected"); 
     status.setTextFill(Color.GREEN); 


    //pb.setProgress(1.0); 
    Parent root = FXMLLoader.load(getClass().getResource("Design.fxml")); 
    Scene primary = new Scene(root,1024,768); 
    primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 
    System.out.println("Text changing to COnnected"); 
    status.setTextFill(Color.GREEN); 
    Thread.sleep(2000); 
    Main.window.setScene(primary); 

} 

問題は「接続済み」に変更する必要があります。それは私のシーンが切り替わっされようとしているだけのときに変化する....

+1

だけで、なぜあなたはスレッド –

答えて

1

あなたには、いくつかの長い実行中の操作を持っている場合は、Taskを使用する必要があります。そうでない場合、その操作がJavaFXアプリケーションスレッドから呼び出されると、GUIがブロックされます。

あなたはTaskあなたはJavaFXのアプリケーションスレッド上でコードを実行する、Platform.runlaterを使用する必要がありますから、GUI更新する場合:あなたのGUIのNodesPlatform.runlater

アップデートを常にオンに実行する必要がありますJavaFxスレッド

Listenerの中のstatusbuttonに更新するとうまくいくはずです。 dbConnect()はある程度の時間がかかる

button.setOnAction(evt -> { 
     dbConnect(); 
     status.setText("Connected"); 
     // ... 
    }); 

場合は、使用することができTask:あなたがデータベースに接続されているので、あなたが維持するためにTaskServiceを使用してバックグラウンドで実行するには、このコードを配置する必要があり

Task<Void> longRunningTask = new Task<Void>() { 

     @Override 
     protected Void call() throws Exception { 
      dbConnect(); 
      Platform.runLater(() -> status.setText("Connected")); 
      return null; 
     } 
    }; 


    button.setOnAction(e -> { 
     new Thread(longRunningTask).start(); 
    }); 
+0

内Platform.runLaterを入れなかったそうでない,,,頼みます'Task'の中で' Platform.runLater'を実行する必要があります。 'Task'は、' setOnSucceeded'や 'SetOnFailed'のようなイベントを使って、タスクが終了したときに聴くメカニズムを提供します。 – leobelizquierdo

0

ユーザ入力に応答するGUIスレッド。 GUIスレッドでのみ、ビューの状態を更新できることを覚えておいてください(あなたのケースのテキストの値を変更する)。あなたは、java Threadを使用し、内部のコードは、GUIのスレッドではなく、あなたが間違った方法で使用している、あなたのケースで歳差運動する予定であることを意味しているPlatform.runLaterを使用することができます。まず、データベースに接続するためのロジックは、スレッドの方法run内および方法仕上げた後もテキストの値を設定し、後にやりたいはずです。また、すべてのプロセスが完了したときに新しいSceneを表示して、テキストの変更をユーザーに見られるようにすることもできます。あなたは、このようにコードを変更することができます

private void changeSC() throws IOException, InterruptedException, SQLException 
{ 
    Thread thrd = new Thread() { 

    public void run() { 
     dbConnect(); 
     Platform.runLater(new Runnable() { 
      @Override public void run() { 
       status.setText("Connected"); 
       status.setTextFill(Color.GREEN); 
       //pb.setProgress(1.0); 
       Parent root = FXMLLoader.load(getClass().getResource("Design.fxml")); 
       Scene primary = new Scene(root,1024,768); 
       primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 
       System.out.println("Text changing to COnnected"); 
       status.setTextFill(Color.GREEN); 
       Main.window.setScene(primary); 
       } 
     }); 
    } 
    }; 
    thrd.start(); 
} 

あなたが明示的にPlatform.runLaterに対処するために持っていけないTaskを使用して選択した場合。あなただけの、タスク(クラスTaskの実装)を作成するJava Threadの内側にこれをラップし、さまざまなイベント(:setOnSucceededなど)のためにそれとセットハンドラを起動する必要があります。これはTaskを使用してコードです:

private void changeSC() throws IOException, InterruptedException, SQLException 
{ 
    Task<Void> task = new Task<Void>(){ 
     @Overrdie 
     protected Void call() { 
      dbConnect(); 
      return null; 
     } 
    }; 
    //start Task 
    Thread t = new Thread(task); 
    t.setDaemon(true); // thread will not prevent application shutdown 
    t.start(); 

    task.setOnSucceeded(event -> { 
     Parent root = FXMLLoader.load(getClass().getResource("Design.fxml")); 
     Scene primary = new Scene(root,1024,768); 
     primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 
     System.out.println("Text changing to COnnected"); 
     status.setTextFill(Color.GREEN); 
     Main.window.setScene(primary); 
    }); 


} 
OK
0

i)は(task.SetonFailedを設定することで、それを修正:)

+0

私は理解していない、どのようにあなたのタスク(あなたが1つを使用している場合)が失敗したことを意味するイベントをキャッチして固定? – leobelizquierdo