2017-05-23 6 views
0

JavaFXのログインページを少し進捗バーで作成しようとしています。しかし、毎回私は資格情報をチェックしたいので、タスクは失敗し、setOnFailed()メソッドに私をスローします。私はそれが何を変えるのか、どのように働かせるのかは知らない。ここでJavaFXタスクは、ログイン情報を取得するたびに状態が変わるように変更します。

は、これまでの私のコードです:

public class Login extends Base_controller implements Initializable{ 
    private ProgressBar pb = new ProgressBar(); 
    private TextField username; 
    private PasswordField password; 

    public void start(Stage primaryStage) throws Exception { 

     // Setting structure and components 
     Label username_lbl = new Label(); 
     Label password_lbl = new Label(); 
     username_lbl.setText("Username:"); 
     password_lbl.setText("Password:"); 

     username = new TextField(); 
     password = new PasswordField(); 

     //some code 

     VBox root = new VBox(); 
     root.setAlignment(Pos.CENTER); 
     root.getChildren().addAll(container0, container1, container2, container3); 
     root.setSpacing(30); 


     // button action listener 
     test.setOnAction(e->{ 
      Platform.runLater(() -> { 
       root.getChildren().add(pb); 
      }); 

      Task<Void> validatePassword = new Task<Void>(){ 
       @Override 
       protected Void call() throws Exception { 
        validatePassword(password, username); 
        return null; 
       } 
      }; 

      validatePassword.setOnSucceeded(ee->{ // when it finishes successfully 
       try { 
        root.getChildren().remove(pb); // remove the progress bar 
       } catch (Exception e1) { 
        e1.printStackTrace(); 
       } 

       User = dbHandler.getPersonByUsername(username.getText()); // Set up global variable 
       Role = dbHandler.getPersonRole(User.getEmail()); 
       MainStage = (Stage) anchorPane.getScene().getWindow(); 
       Parent parent = null; 
       try { 
        parent = FXMLLoader.load(getClass().getResource("/menu.fxml")); 
       } catch (IOException e1) { 
        e1.printStackTrace(); 
       } 
       Scene scene = new Scene(parent); 
       MainStage.setScene(scene); 
       MainStage.setTitle("Menu | Administration of Musical Courses"); 
       MainStage.show(); 
      }); 

      validatePassword.setOnFailed(eee->{ // if it fails (that will be indicated by the returned alert message) 
       System.out.println("Failed"); 
       try { 
        root.getChildren().remove(pb); // remove it anyway but inform your user 
        Alert alert = new Alert(Alert.AlertType.ERROR, "Wrong Password", ButtonType.OK); 
        alert.showAndWait(); 
       } catch (Exception e1) { 
        e1.printStackTrace(); 
       } 
      }); 

      new Thread(validatePassword).start(); // add the task to a thread and start it 
     }); 

     Scene scene = new Scene(root, 600,400); 
     primaryStage.setScene(scene); 
     primaryStage.setTitle("Login | Administration of Musical Courses"); 

     primaryStage.show(); 
    } 

    // validate here in this method 
    public void validatePassword(TextField password, TextField username) 
     if (checkLogin()) { 
      new Alert(Alert.AlertType.ERROR); 
     } 
    } 

    public boolean checkLogin(){ 
     return BCrypt.checkpw(password.getText(), dbHandler.getLoginByUsername(username.getText()).getPassword()); 
    } 
} 

データベースからデータを取得するときには、常にvalidatePassword方法で失敗しました。何らかの理由でデータベースを呼び出すと、タスクが失敗する可能性はありますか?コードを変更して動作させるにはどうすればよいですか?

答えて

3

call()メソッドから例外がスローされた場合にのみ、タスクは失敗した状態になります。

validatePassword.setOnFailed(eee->{ // if it fails (that will be indicated by the returned alert message) 
    System.out.println("Failed"); 
    validatePassword.getException().printStackTrace(); 
    try { 
     root.getChildren().remove(pb); // remove it anyway but inform your user 
     Alert alert = new Alert(Alert.AlertType.ERROR, "Wrong Password", ButtonType.OK); 
     alert.showAndWait(); 
    } catch (Exception e1) { 
     e1.printStackTrace(); 
    } 
}); 

私は本当にあなたのvalidatePassword()方法を理解していない:あなたはその後、read to see what went wrongできる例外のスタックトレースを、見にonFailedハンドラ内でvalidatePassword.getException().printStackTrace()を置くことができる

if (checkLogin()) { 
    new Alert(...); 
} 

checkLogin()が真Alertが作成されますが、実際には使用されません(あなたは本当にここで何を意図していますか?)。このメソッドは、バックグラウンドスレッドから呼び出されることに注意してください(タスクのcall()メソッドから呼び出されるため)、FXアプリケーションスレッドを使用していない場合はAlertを作成することはできません。だから私は例外がスローされる原因と思われます。onFailedハンドラにあなたを送ります:スタックトレースをチェックすることでこれが確認されます。

より自然なアプローチは、タスクがあなたがonSucceededハンドラで扱う可能性がある、ログインが成功したか否かを示すBooleanを返す持っているだろう:

test.setOnAction(e->{ 
    Platform.runLater(() -> { 
     root.getChildren().add(pb); 
    }); 

    Task<Boolean> validatePassword = new Task<Boolean>(){ 
     @Override 
     protected Boolean call() throws Exception { 
      return checkLogin(); 
     } 
    }; 

    validatePassword.setOnSucceeded(ee->{ // when it finishes successfully 
     // this cannot throw an exception, there is no need for a try-catch; 
     root.getChildren().remove(pb); // remove the progress bar 

     if (validatePassword.getValue()) { 
      User = dbHandler.getPersonByUsername(username.getText()); // Set up global variable 
      Role = dbHandler.getPersonRole(User.getEmail()); 
      MainStage = (Stage) anchorPane.getScene().getWindow(); 
      Parent parent = null; 
      try { 
       parent = FXMLLoader.load(getClass().getResource("/menu.fxml")); 
      } catch (IOException e1) { 
       e1.printStackTrace(); 
      } 
      Scene scene = new Scene(parent); 
      MainStage.setScene(scene); 
      MainStage.setTitle("Menu | Administration of Musical Courses"); 
      MainStage.show(); 
     } else { 
      // handle failed login... this is on the FX Application Thread so 
      // you can show an Alert... 
      Alert alert = new Alert(Alert.AlertType.ERROR, "Wrong Password", ButtonType.OK); 
      alert.show(); 
     } 
    }); 

    validatePassword.setOnFailed(eee->{ 
     // exception was thrown trying to validate password 
     validatePassword.getException().printStackTrace(); 
     // inform user something went wrong... 
     Alert alert = new Alert(Alert.AlertType.ERROR, "Something went wrong", ButtonType.OK); 
     alert.show(); 
    }); 

    new Thread(validatePassword).start(); // add the task to a thread and start it 
}); 
+0

&James_D私はちょうど勉強、ありがとうマルチスレッドと私はタスククラスが異なると思った。私は自分のコードを変更し、今すぐ動作します。 –

+0

@TomášZajdaライフサイクルの説明については、[スーパークラスのドキュメント、Worker'](http://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Worker.html)を参照してください。 –

関連する問題