如何在javaFX中将光标更改为等待的同时执行后台任务?

如何在javaFX中将光标更改为等待的同时执行后台任务?,java,javafx,background-task,Java,Javafx,Background Task,我有一个应用程序,它在登录时通过接口类访问数据库。登录过程会导致应用程序在访问数据库时有一段时间没有响应,因此我一直在研究线程和等待光标,以使其能够顺利运行。我曾尝试通过web和堆栈溢出上的许多示例使用线程,但我的方法似乎不起作用,我收到java.lang.IllegalStateException:不在FX应用程序线程上;currentThread=Thread-4异常,我不确定如何从这里开始。我试图做的是在后台线程运行loginLoaderything()方法时将光标更改为等待模式(尽管我没

我有一个应用程序,它在登录时通过接口类访问数据库。登录过程会导致应用程序在访问数据库时有一段时间没有响应,因此我一直在研究线程和等待光标,以使其能够顺利运行。我曾尝试通过web和堆栈溢出上的许多示例使用线程,但我的方法似乎不起作用,我收到java.lang.IllegalStateException:不在FX应用程序线程上;currentThread=Thread-4异常,我不确定如何从这里开始。我试图做的是在后台线程运行loginLoaderything()方法时将光标更改为等待模式(尽管我没有在其中包含代码,因为它太长)。这是我的控制器类:

package main.java.gui;

import javafx.application.Platform;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Cursor;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import main.java.databaseInterface.BackendInterface;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.CountDownLatch;

public class LoginController implements Initializable {


    private BackendInterface backendInterface;
    private DashboardController dashboardController;
    private StudentsController studentsController;
    private ConsultationController consultationController;
    private CreateStudentController createStudentController;
    private CreateConsultationController createConsultationController;

    @FXML
    TextField username;

    @FXML
    PasswordField password;

    @FXML
    Button loginButton;

    @FXML
    Label loginLabel;

    @FXML
    public void loginButtonPress(ActionEvent event) {

        Service<Void> service = new Service<Void>() {
            @Override
            protected Task<Void> createTask() {
                return new Task<Void>() {
                    @Override
                    protected Void call() throws Exception {

                        loginLoadEverything();

                        final CountDownLatch latch = new CountDownLatch(1);
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                try {

                                    Scene s1 = loginLabel.getScene();
                                    s1.setCursor(Cursor.WAIT);

                                } finally {
                                    latch.countDown();
                                }
                            }
                        });
                        latch.await();
                        return null;
                    }
                };
            }
        };
        service.start();

    }

    public void loginLoadEverything() {

         //chance to true when complete
    if (username.getText().isEmpty() == false || password.getText().isEmpty() == false) {

        loginLabel.setText("Please enter data in the fields below");

    } else {

        username.setText("-----");
        password.setText("-----");
        //initialises backend interface with username and password
        backendInterface = new BackendInterface(username.getText(), password.getText().toCharArray());

        // Open a connection to the database

        if (backendInterface.openConnection()) {

            //return and print response
            System.out.println(backendInterface.getConnectionResponse());

            //directs the user to the dashboard after successful login
            try {
                if (backendInterface.getAllStudents() &&
                        backendInterface.getAllConsultations() &&
                        backendInterface.getCourses() &&
                        backendInterface.getConsultationCategories() &&
                        backendInterface.getConsultationPriorities()) {


                    FXMLLoader loader1 = new FXMLLoader();
                    loader1.setLocation(getClass().getResource("/main/res/dashboard.fxml"));
                    loader1.load();
                    Parent p = loader1.getRoot();
                    Stage stage = new Stage();
                    stage.setScene(new Scene(p));
                    stage.show();

                    //set instances to the dashboard controller
                    dashboardController = loader1.getController();
                    dashboardController.setBackendInterface(backendInterface); //pass backendInterface object to controller
                    dashboardController.setDashboardController(loader1.getController()); //pass dashboard as reference

                    //load images
                    Image logoutImage = new Image(getClass().getResourceAsStream("images/logout.png"));
                    Image userImage = new Image(getClass().getResourceAsStream("images/users.png"));
                    Image calendarImage = new Image(getClass().getResourceAsStream("images/calendar.png"));
                    Image leftArrowImage = new Image(getClass().getResourceAsStream("images/leftArrow.png"));
                    Image notepadImage = new Image(getClass().getResourceAsStream("images/notepad.png"));

                    //set images
                    dashboardController.studentLabel.setGraphic(new ImageView(userImage));
                    dashboardController.logoutLabel.setGraphic(new ImageView(logoutImage));
                    dashboardController.consultationLabel.setGraphic(new ImageView(notepadImage));

    } else {
           system.out.println(backendInterface.getExceptionMessage);
    }


    @Override
    public void initialize(URL location, ResourceBundle resources) {



}
package main.java.gui;
导入javafx.application.Platform;
导入javafx.concurrent.Service;
导入javafx.concurrent.Task;
导入javafx.event.ActionEvent;
导入javafx.fxml.fxml;
导入javafx.fxml.fxmloader;
导入javafx.fxml.Initializable;
导入javafx.scene.Cursor;
导入javafx.scene.Parent;
导入javafx.scene.scene;
导入javafx.scene.control.*;
导入javafx.scene.image.image;
导入javafx.scene.image.ImageView;
导入javafx.stage.stage;
导入main.java.databaseInterface.BackendInterface;
导入java.net.URL;
导入java.util.ResourceBundle;
导入java.util.concurrent.CountDownLatch;
公共类LoginController实现可初始化{
专用后端接口后端接口;
专用仪表板控制器仪表板控制器;
私人学生控制人学生控制人;
私人咨询控制人咨询控制人;
私有CreateStudentController CreateStudentController;
私有CreateConsultationController CreateConsultationController;
@FXML
TextField用户名;
@FXML
密码字段密码;
@FXML
按钮登录按钮;
@FXML
标签登录标签;
@FXML
public void loginButtonPress(ActionEvent事件){
服务=新服务(){
@凌驾
受保护的任务createTask(){
返回新任务(){
@凌驾
受保护的Void调用()引发异常{
loginLoadEverything();
最终倒计时闩锁=新倒计时闩锁(1);
Platform.runLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
场景s1=loginLabel.getScene();
s1.setCursor(Cursor.WAIT);
}最后{
倒计时();
}
}
});
satch.wait();
返回null;
}
};
}
};
service.start();
}
public void loginLoadEverything(){
//完成后有机会成为现实
if(username.getText().isEmpty()==false | | password.getText().isEmpty()==false){
loginLabel.setText(“请在下面的字段中输入数据”);
}否则{
username.setText(“----”);
password.setText(“----”);
//使用用户名和密码初始化后端接口
backendInterface=新的backendInterface(username.getText(),password.getText().toCharArray());
//打开与数据库的连接
if(backendInterface.openConnection()){
//返回和打印响应
System.out.println(backendInterface.getConnectionResponse());
//成功登录后将用户引导到仪表板
试一试{
if(backendInterface.getAllStudents()&&
backendInterface.getAllConsultations()&&
backendInterface.getCourses()&&
backendInterface.getConsultationCategories()&&
backendInterface.getConsultationPriorities()){
FXMLLoader loader1=新的FXMLLoader();
setLocation(getClass().getResource(“/main/res/dashboard.fxml”);
loader1.load();
父p=loader1.getRoot();
阶段=新阶段();
舞台场景(新场景(p));
stage.show();
//将实例设置为仪表板控制器
dashboardController=loader1.getController();
dashboardController.setBackendInterface(backendInterface);//将backendInterface对象传递给控制器

dashboardController.setDashboardController(loader1.getController());//将dashboard作为引用传递 //加载图像 Image logoutImage=新图像(getClass().getResourceAsStream(“images/logout.png”); Image userImage=新图像(getClass().getResourceAsStream(“images/users.png”); Image calendarImage=新图像(getClass().getResourceAsStream(“images/calendar.png”); Image leftArrow Image=新图像(getClass().getResourceAsStream(“images/leftArrow.png”); Image notepad Image=新图像(getClass().getResourceAsStream(“images/notepad.png”); //设置图像 dashboardController.studentLabel.setGraphic(新的ImageView(userImage)); dashboardController.logoutLabel.setGraphic(新图像视图(logoutImage)); dashboardController.consultationLabel.setGraphic(新的ImageView(notepadImage)); }否则{ system.out.println(backendInterface.getExceptionMessage); } @凌驾 公共无效初始
@FXML
public void loginButtonPress(ActionEvent event) {

    if (( ! username.getText().isEmpty()) || (! password.getText().isEmpty()) ) {

        loginLabel.setText("Please enter data in the fields below");

    } else {

        // I assume you want these values before you set them to "-----", no???
        final String uName = username.getText();
        final char[] pw = password.getText().toCharArray();

        username.setText("-----");
        password.setText("-----");

        // create task for retrieving data:

        Task<BackendInterface> loadDataTask = new Task<BackendInterface>() {

            @Override
            public BackendInterface call() throws Exception {

                BackendInterface backendInterface = new BackendInterface(uName, pw);
                if (backendInterface.openConnection()) {

                    if (backendInterface.getAllStudents() &&
                        backendInterface.getAllConsultations() &&
                        backendInterface.getCourses() &&
                        backendInterface.getConsultationCategories() &&
                        backendInterface.getConsultationPriorities()) {

                        return backendInterface ;
                    }
                 }

                 // maybe throw an exception here, depending on your requirements...
                 return null ;
            }

        };

        // show UI on task completion:

    loadDataTask.setOnSucceeded(e -> {

        BackendInterface backendInterface = loadDataTask.getValue();

        if (backendInterface == null) {
            // something went wrong... bail, or probably show error message...
            return ;
        }

        FXMLLoader loader1 = new FXMLLoader();
        loader1.setLocation(getClass().getResource("/main/res/dashboard.fxml"));
        Parent p = loader1.load();
        DashboardController controller = loader.getController();
        controller.setBackendInterface(backendInterface);

        Stage stage = new Stage();
        stage.setScene(new Scene(p));
        stage.show();

        // etc etc with your Images, etc (not sure why this isn't done in DashboardController though...)

        // set cursor back to default:
        loginLabel.getScene().setCursor(Cursor.DEFAULT);
    });

    loadDataTask.setOnFailed(e -> {
        // show error message or otherwise handle database exception here
    });

    // set cursor to WAIT:
    loginLabel.getScene().setCursor(Cursor.WAIT);

    // and run task in a background thread:
    Thread t = new Thread(loadDataTask);
    t.start();

}