2012-12-10 1 views
11

私はJavaFXアプリケーションで作業しています。私のシナリオでは、2つのオプションOKCancelでパスワードを取るJavaFXで作成されたパスワードプロンプトを表示します。私はユーザーが入力したパスワードを返しました。javafxプラットフォームrunlaterの結果を返します

パスワードダイアログを示す私のクラスである -

public static String showPasswordDialog(String title, String message, Stage parentStage, double w, double h) { 
    try { 
     Stage stage = new Stage(); 
     PasswordDialogController controller = (PasswordDialogController) Utility.replaceScene("Password.fxml", stage); 
     passwordDialogController.init(stage, message, "/images/password.png"); 
     if (parentStage != null) { 
      stage.initOwner(parentStage); 
     } 
     stage.initModality(Modality.WINDOW_MODAL); 
     stage.initStyle(StageStyle.UTILITY); 
     stage.setResizable(false); 
     stage.setWidth(w); 
     stage.setHeight(h);     
     stage.showAndWait(); 
     return controller.getPassword(); 
    } catch (Exception ex) { 
     return null; 
    } 

、下記実際にそうでない場合は、このプロンプトは、他のUI上に表示されますので、私はPlatform.runlater()内でこれを取り巻くする必要があるパスワードプロンプトを表示するように私のコードNot on FX application threadを投げます。私は正しいパスワードが表示されるまでこのパスワードプロンプトを表示する必要があります。私がrunlaterの中にパスワードを表示するようにした場合、どうすればパスワードの価値を得ることができますか?

他にも良い方法がありますか?

final String sPassword = null; 

      do { 
      Platform.runLater(new Runnable() { 

       @Override 
       public void run() { 
        sPassword = JavaFXDialog.showPasswordDialog(sTaskName + "Password", "Enter the password:", parentStage, 400.0, 160.0); 
       } 
      }); 

      if (sPassword == null) { 
       System.out.println("Entering password cancelled."); 
       throw new Exception("Cancel"); 
      } 
     } while (sPassword.equalsIgnoreCase("")); 

答えて

27

FutureTaskオブジェクト内にコードをラップすることをおすすめします。 FutureTaskは、あるスレッド(通常はあなたのケースではイベントキュー)のコードの一部を実行し、他のスレッドで安全に取得するのに便利です(とりわけ)。 FutureTask#getFutureTask#runが呼び出されるまで、したがって、パスワード・プロンプトが次のようになりますブロックします:Runnableを実装し

final FutureTask query = new FutureTask(new Callable() { 
    @Override 
    public Object call() throws Exception { 
     return queryPassword(); 
    } 
}); 
Platform.runLater(query); 
System.out.println(query.get()); 

FutureTaskとして、あなたはPlatform#runLater(...)に直接渡すことができます。 queryPassword()はイベントキューに入れられ、そのメソッドが完了するまでgetブロックを呼び出すことになります。もちろん、パスワードが実際に一致するまでループ内でこのコードを呼び出すことができます。

8

重要

このコードを使用すると、JavaFXアプリケーションのスレッドにないコードを持っているとあなたにGUIを表示するには、JavaFXアプリケーションのスレッド上にあるコードを呼び出したいときの特定の場合であるが、 JavaFXアプリケーションスレッドの処理を続行する前に、そのGUIから結果を取得します。

以下のコードスニペットでCountdownLatch.awaitを呼び出すときは、JavaFXアプリケーションスレッドを使用してはいけません。 JavaFXアプリケーションスレッドでCountDownLatch.awaitを呼び出すと、アプリケーションがデッドロックされます。それ以外に、JavaFXアプリケーションスレッド上にすでに存在する場合は、JavaFXアプリケーションスレッドで何かを実行するためにPlatform.runLaterを呼び出す必要はありません。

ほとんどの場合、あなたはJavaFXアプリケーションスレッドかどうかを知っています。あなたがわからない場合は、Platform.isFxApplicationThread()に電話をかけてスレッドをチェックすることができます。


CountDownLatchを使用する別の方法です。 JavaFXのダイアログができ、結果を取得したまで、ここで


final CountDownLatch latch = new CountDownLatch(1); 
final StringProperty passwordProperty = new SimpleStringProperty(); 
Platform.runLater(new Runnable() { 
    @Override public void run() { 
     passwordProperty.set(queryPassword()); 
     latch.countDown(); 
    } 
}); 
latch.await();  
System.out.println(passwordProperty.get()); 
が非JavaFXアプリケーションのスレッドの実行を中断したCountDownLatchの使用方法を示すいくつかの実行可能なサンプルコードがあり、より良い;-)けれども私はSarcanの方法が好き非JavaFXアプリケーションスレッドによってアクセスされます。

アプリケーションは、ユーザーがJavaFXダイアログで正しいパスワードを入力するまで、アプリケーションのJavaFXランチャースレッドが続行されないようにします。アクセス許可の段階は、正しいパスワードが入力されるまで表示されません。

enterpassword     access granted

import javafx.application.*; 
import javafx.beans.property.*; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.scene.layout.*; 
import javafx.scene.text.TextAlignment; 
import javafx.stage.*; 

import java.util.concurrent.CountDownLatch; 

public class PasswordPrompter extends Application { 
    final StringProperty passwordProperty = new SimpleStringProperty(); 
    @Override public void init() { 
    final CountDownLatch latch = new CountDownLatch(1); 

    Platform.runLater(new Runnable() { 
     @Override public void run() { 
     passwordProperty.set(new PasswordPrompt(null).getPassword()); 
     latch.countDown(); 
     } 
    }); 

    try { 
     latch.await(); 
    } catch (InterruptedException e) { 
     Platform.exit(); 
    } 

    System.out.println(passwordProperty.get()); 
    } 

    @Override public void start(final Stage stage) { 
    Label welcomeMessage = new Label("Access Granted\nwith password\n" + passwordProperty.get()); 
    welcomeMessage.setTextAlignment(TextAlignment.CENTER); 

    StackPane layout = new StackPane(); 
    layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 20px;"); 
    layout.getChildren().setAll(welcomeMessage); 
    stage.setScene(new Scene(layout)); 

    stage.show(); 
    } 

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

class PasswordPrompt { 
    final Window owner; 

    PasswordPrompt(Window owner) { 
    this.owner = owner; 
    } 

    public String getPassword() { 
    final Stage dialog = new Stage(); 
    dialog.setTitle("Pass is sesame"); 
    dialog.initOwner(owner); 
    dialog.initStyle(StageStyle.UTILITY); 
    dialog.initModality(Modality.WINDOW_MODAL); 
    dialog.setOnCloseRequest(new EventHandler<WindowEvent>() { 
     @Override public void handle(WindowEvent windowEvent) { 
     Platform.exit(); 
     } 
    }); 

    final TextField textField = new TextField(); 
    textField.setPromptText("Enter sesame"); 
    final Button submitButton = new Button("Submit"); 
    submitButton.setDefaultButton(true); 
    submitButton.setOnAction(new EventHandler<ActionEvent>() { 
     @Override public void handle(ActionEvent t) { 
     if ("sesame".equals(textField.getText())) { 
      dialog.close(); 
     } 
     } 
    }); 

    final VBox layout = new VBox(10); 
    layout.setAlignment(Pos.CENTER_RIGHT); 
    layout.setStyle("-fx-background-color: azure; -fx-padding: 10;"); 
    layout.getChildren().setAll(textField, submitButton); 

    dialog.setScene(new Scene(layout)); 
    dialog.showAndWait(); 

    return textField.getText(); 
    } 
} 

上記のプログラムは、パスワードを表示したり、ログインすると、あなたが実際のアプリケーションでどうなるものではありません、デモンストレーションの目的のために純粋に画面やコンソールにパスワードを出力します。

+0

いくつかの奇妙な理由により、これは期待どおりに機能しません。それは待って立ち往生し、Runnable.runは決して呼び出されませんでした。 – xar

+0

それは私のために働きます、私は実用的なサンプルを追加して、使用法をさらに実証しました。 – jewelsea

+0

@xar JavaFXアプリケーションスレッドで、おそらく 'latch.await()'が呼び出されました。説明のために答えにテキストを追加しました。 – jewelsea

関連する問題