【问题标题】:Trouble setting program flow to correctly run a function无法设置程序流程以正确运行功能
【发布时间】:2020-11-25 20:57:41
【问题描述】:

我有一个类任务,它使用菜单布局处理多个任务,类任务通过设置阶段检查应用程序流程,用菜单场景列出所有单个任务。我想使用自己的类从可用列表中运行一些任务,如下所示:

Tasks.java:

    package tasks;
    
    import javafx.application.Application;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.layout.VBox;
    import javafx.scene.control.Button;
    
    public class Tasks extends Application
    {
        private Stage window;
        private Scene menuScene;
        private Task1 task1;
    
        public Tasks()
        {
            this.window=null;
            this.menuScene=null;
            this.task1=null;
        }
    
        private void setMenu()
        {
            VBox menu=new VBox();
    
            Button newTask1Button=new Button("New Task 1");
            newTask1Button.setOnAction(clickEvent -> this.startNewTask1());
            menu.getChildren().add(newTask1Button);
    
            //More buttons
    
            this.menuScene=new Scene(menu,400,600);
        
            this.window.setScene(this.menuScene);
        }
    
        private void startNewTask1()
        {
            this.task1=new Task1(this.window);
            this.launchTask1();
        }
    
        private void launchTask1()
        {
            if(this.task1!=null)
            {
                int task1State=1;
                //while(task1State==1) //To re-run for pause state
                //{
                    task1State=this.task1.runTask1();
                    System.out.println("Task1 is in state "+task1State); //In no way part of program, just for debugging. Always give state=-1
                    //If 1-Paused, then display pause Menu for task1, by calling this.task1.paused(); and then again based on user input re-run runTask1
                    //If 0-Exit, then change the scene back to menuScene and quit the function
                //}
            }
        }
    
        @Override
        public void start(Stage primaryStage)
        {
            this.window=primaryStage;
            this.window.setTitle("Tasks");
    
            this.setMenu();
    
            this.window.show();
        }
    
        public static void main(String[] args)
        {
            Application.launch(args);
        }
    }

Task1.java:

    package tasks;
    
    import javafx.stage.Stage;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.layout.HBox;
    import javafx.scene.control.Button;
    
    class Task1
    {
        private Stage window;
        private Scene task1Scene;
        private boolean intialised;
    
        private int state;
    
        public Task1()
        {
        }
        public Task1(Stage _window)
        {
            this.window=_window;
            this.task1Scene=null; //Will be set later
            this.intialised=false;
            this.state=-1;
        }
    
        private Scene createScene()
        {
            //Creates some GUI to interact
            
            //Buttons in End, to control exit
            HBox menu=new HBox();
    
            Button pauseButton=new Button("Pause");
            pauseButton.setOnAction(clickEvent -> this.state=1);
            menu.getChildren().add(pauseButton);
            
            Button exitButton=new Button("Exit");
            exitButton.setOnAction(clickEvent -> this.state=0);
            menu.getChildren().add(exitButton);
    
            Scene scene=new Scene(menu,400,600);
    
            return scene;
        }
    
        private void setupControls()
        {
            //To assign event handlers to interact with GUI
        }
    
        public int runTask1()
        {
            if(!this.intialised)
                this.task1Scene=this.createScene();
            this.window.setScene(this.task1Scene);
    
            this.setupControls();

            //while(this.state==-1);
        
            return this.state;
        }
    }

我面临的问题是,函数 runTask1() 总是立即返回,即使使用 Task1 的事件处理程序分配的操作仍在运行并且没有生成退出事件。

我尝试通过设置一个名为 state 的实例变量并将其设置为 -1 并放置一个 while 循环直到该状态变量未被修改来解决此问题。但这完全停止了 GUI。

我后来通过谷歌搜索知道了它的原因,但无法确定用哪种方法解决这个问题。

在某些地方,建议使用线程(不确定如何,我不希望程序中运行多个进程),在某些地方,还建议设置另一个事件处理程序(但是,它们运行的​​是不同的start() 函数(继承自 Application)本身中的流程,它更多的是转移流程而不是向后返回)。

我应该如何编写代码以保持只运行runTask1() 直到它未完成,然后依次返回到launchTask1()

【问题讨论】:

标签: java javafx


【解决方案1】:

Task1 类中方法 runTask1() 中的无限 while 循环正在冻结 JavaFX application thread。只需将其删除。

基本上你的Task1 类是另一个Scene,所以当你点击Tasks 类中的按钮newTask1Button 时,你只想设置一个新的Scene

这里是 Task1 类,需要进行更改。

package tasks;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.control.Button;

public class Task1 {
    private Stage window;
    private Scene task1Scene;
    private boolean intialised;

    private int state;

    public Task1() {
    }

    public Task1(Stage _window) {
        this.window = _window;
        this.task1Scene = null; // Will be set later
        this.intialised = false;
        this.state = -1;
    }

    private Scene createScene() {
        // Creates some GUI to interact

        // Buttons in End, to control exit
        HBox menu = new HBox();

        Button pauseButton = new Button("Pause");
        pauseButton.setOnAction(clickEvent -> this.state = 1);
        menu.getChildren().add(pauseButton);

        Button exitButton = new Button("Exit");
        exitButton.setOnAction(clickEvent -> this.state = 0);
        menu.getChildren().add(exitButton);

        Scene scene = new Scene(menu, 400, 600);

        return scene;
    }

    private void setupControls() {
        // To assign event handlers to interact with GUI
    }

    public int runTask1() {
        if (!this.intialised)
            this.task1Scene = this.createScene();
        this.window.setScene(this.task1Scene);

        this.setupControls();

//        while (this.state == -1)
//            ;

        return this.state;
    }
}

如您所见,我只是注释掉了while 循环。 JavaFX 应用程序线程包含一个循环,该循环等待用户操作发生,例如移动鼠标或在键盘上键入一个键。您不必在代码中处理它。

编辑

由于您问题代码中的拼写错误,您在对我的回答的评论中提到并且您在随后的编辑中更正了您的问题,我正在编辑我的答案。

JavaFX 应用程序的工作方式是对用户操作做出反应。当用户在Task1 类中单击pauseButtonexitButton 时,您希望在Task1 类中的“状态”发生更改时通知Tasks 类。根据您发布的代码,您可以从pauseButton 的事件处理程序回调类Tasks

班级Task1.
(注意注释 CHANGE HERE 和构造函数中的额外参数。)

package tasks;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.control.Button;

public class Task1 {
    private Tasks tasks;
    private Stage window;
    private Scene task1Scene;
    private boolean intialised;

    private int state;

    public Task1(Stage _window, Tasks tasks) {
        this.tasks = tasks;
        this.window = _window;
        this.task1Scene = null; // Will be set later
        this.intialised = false;
        this.state = -1;
    }

    private Scene createScene() {
        HBox menu = new HBox();
        Button pauseButton = new Button("Pause");
        pauseButton.setOnAction(clickEvent -> tasks.setState(this.state = 1)); // CHANGE HERE
        menu.getChildren().add(pauseButton);
        Button exitButton = new Button("Exit");
        exitButton.setOnAction(clickEvent -> this.state = 0);
        menu.getChildren().add(exitButton);
        Scene scene = new Scene(menu, 400, 600);
        return scene;
    }

    private void setupControls() {
        // To assign event handlers to interact with GUI
    }

    public int runTask1() {
        if (!this.intialised) {
            this.task1Scene = this.createScene();
        }
        this.window.setScene(this.task1Scene);
        this.setupControls();
        return this.state;
    }
}

班级Tasks
(添加方法setState(int)。)

package tasks;

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.control.Button;

public class Tasks extends Application {
    private Stage window;
    private Scene menuScene;
    private Task1 task1;

    public Tasks() {
        this.window = null;
        this.menuScene = null;
        this.task1 = null;
    }

    private void setMenu() {
        VBox menu = new VBox();
        Button newTask1Button = new Button("New Task 1");
        newTask1Button.setOnAction(clickEvent -> this.startNewTask1());
        menu.getChildren().add(newTask1Button);
        this.menuScene = new Scene(menu, 400, 600);
        this.window.setScene(this.menuScene);
    }

    private void startNewTask1() {
        this.task1 = new Task1(this.window, this);
        this.launchTask1();
    }

    private void launchTask1() {
        if (this.task1 != null) {
            this.task1.runTask1();
        }
    }

    @Override
    public void start(Stage primaryStage) {
        this.window = primaryStage;
        this.window.setTitle("Tasks");
        this.setMenu();
        this.window.show();
    }

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

    public void setState(int task1State) {
        System.out.println("Task1 is in state " + task1State); // In no way part of program,
                                                               // just for debugging.
    }
}

【讨论】:

  • 我只是早些时候才意识到这个问题(为此道歉,我忘了在代码中评论它)。该函数会提前返回,而不会一直停留在它上面,直到发起有效的返回。我想根据用户选择从函数 {0,1} 返回特定代码,但它返回默认值 -1。
  • 感谢创建二进制关联的想法,我最好回调任务,而不是尝试返回。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多