加载查询时使进度条可见。 ScalaFx

时间:2015-11-02 03:52:50

标签: scala javafx scalafx

我有一个登录窗口视图,当我点击/按下输入按钮时我想显示一个进度条,同时光滑查询密码。如果我在按钮actionEvent上更改进度条的visible属性,则在查询完成之后才会显示。此外,我不希望进度条在其不可见的情况下占用空间。有人知道怎么做这些事吗?

object SPM extends JFXApp {

/*
* Primary stage: Log in
* */
stage = new PrimaryStage {
// error message hidden label
val errorLabel = new Label()
errorLabel.textFill = Color.Red
errorLabel.font = Font.font("Helvetica", FontWeight.ExtraLight, 12)

val usernameField = new TextField {
  promptText = "User"
  maxWidth = 250
  prefHeight = 35
}

val passwordField = new PasswordField() {
  promptText = "Password"
  maxWidth = 250
  prefHeight = 35
}

val progressBar = new ProgressBar {
  maxWidth = 300
  visible = false
}
title = "Software Project Management"
scene = new Scene(800, 600) {
  root = new VBox {
    spacing = 10
    padding = Insets(20)
    alignment = Pos.Center
    children = List(
      new ImageView {
        image = new Image(
          this.getClass.getResourceAsStream("/images/logo.png"))
        margin = Insets(0, 0, 20, 0)
      },
      new Label {
        text = "Software Project Management"
        font = Font.font("Helvetica", FontWeight.ExtraLight, 32)
      },
      new Label {
        text = "Sign in to get started"
        font = Font.font("Helvetica", FontWeight.Thin, 18)
      },
      errorLabel,
      progressBar,
      usernameField,
      passwordField,
      new Button {
        text = "Enter"
        defaultButton = true
        prefHeight = 35
        font = Font.font("Helvetica", FontWeight.Thin, 18)
        maxWidth = 250
        onAction = (ae: ActionEvent) => {
          progressBar.visible = true
          val password = Users.checkPassword(usernameField.text.value)
          if (password != passwordField.text.value)
            errorLabel.text = "Please re-enter your password"
          else root = chooseProject
        }
      }
    ) // children
  } // root
} // scene

1 个答案:

答案 0 :(得分:1)

您的Button.onAction处理程序正在JavaFX应用程序线程上运行。与用于更新UI的内容相同。当你运行长时间运行的任务时,你应该在一个单独的线程上运行它,它将帮助UI做出正确的反应。常见的方法是使用JavaFX Task。一般模式是这样的:

// Define your task
val task = new javafx.concurrent.Task[T] {
  override def call(): T = {
    // Do your task and return result    
    // Executed off JavaFX Application thread     
  }
  override def succeeded(): Unit = {
    // Update UI to finish processing
    // Executed on JavaFX Application thread     
  }
  override def failed(): Unit = {
    // Handle errors, if any
    // Executed on JavaFX Application thread 
  }
}

// Run your task
val t = new Thread(task, "My Task")
t.setDaemon(true)
t.start()

```

以下是代码中的内容:

  root = new VBox { _root =>
  ...

        onAction = (ae: ActionEvent) => {
          progressBar.visible = true
          _root.disable = true
          //              progressBar.visible = true
          val task = new javafx.concurrent.Task[Boolean] {
            override def call(): Boolean = {
              println("Checking password... ")
              Thread.sleep(3000)
              println("Password checked. ")
              // Assume password is correct
              true
            }
            override def succeeded(): Unit = {
              progressBar.visible = false
              _root.disable = false
              val passwordOK = get()
              if (passwordOK) {
                new Alert(AlertType.Information) {
                  headerText = "Password OK"
                }.showAndWait()
              } else {
                new Alert(AlertType.Warning) {
                  headerText = "Invalid Password"
                }.showAndWait()

              }
            }
            override def failed(): Unit = {
              println("failed")
              progressBar.visible = false
              _root.disable = false
            }
          }

          val t = new Thread(task, "Password Task")
          t.setDaemon(true)
          t.start()
        }