简体   繁体   中英

Creating a Task with JavaFX with a 'wait()' inside

I use javafx, I have a TextField and a Button, when the button is pressed, it saves what is written in the TextField in a String. What I want to create is a method to mark a pause, while waiting for the Button to get pressed.

I have a class named pause.java, where I tried to put a obj.wait(); and a notifyAll(); in the event where the button is pressed, but the window isn't accessible during this time, I can't press the button or enter anything in the TextField.

So what I found was to put the obj.wait(); in a task, then I don't know why but it directly breaks out of the wait.

Here is my pause.java

package net.jpajavafx;

import java.util.logging.*;
import javafx.concurrent.Task;

public class pause {
    Logger logger = Logger.getLogger(pause.class.getName());
    MainController obj = new MainController();

    public void waitinput() {
        Task<Void> sleeper = new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                synchronized (obj) {
                    try {
                        String write = "Waiting for input...";
                        logger.log(Level.INFO, write);
                        obj.wait();
                        logger.log(Level.INFO, "Done");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
        };
        new Thread(sleeper).start();

    }
}

How do I have to modify it to make it wait, while still having access to the GUI?

Here's my code simplified for the problem:

AlbumManager.java, where my main is.

package net.jpajavafx;


import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.*;
import javafx.application.*;
import javafx.fxml.FXMLLoader;

public class AlbumManager extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));
        Scene scene = new Scene(root);

        primaryStage.setTitle("Album Manager");
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static void main(String[] args) {

        launch(args);

    }

}

MainController.java:

package net.jpajavafx;
import javafx.event.ActionEvent;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.fxml.FXML;
import java.util.logging.*;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

public class MainController {

    @FXML
    private TextArea textarea;
    @FXML
    private TextField textfield;

   Variablesstoring stock = new Variablesstoring();
    
    public void ok(ActionEvent event) {
        String getValue = textfield.getText();
        stock.setEntrystr(getValue);          //here i have something to put in an Int, I put it aside to reduce the length
        textfield.setText("");
        notifyAll();
    }
    
    public void startprogram() {
        int etat = 0;
        int run = 1;
        while (run == 1) {
            textarea.setText("1: launch method");
            pause.waitinput();     // here I want to wait for an input
            etat = stock.getEntrystr();
            switch (etat) {
            case 1:
                //runs a method
                break;
            default:
                break;
            }
        }   
    }
}


It's really not clear what you're trying to achieve here that needs a separate thread: all the separate thread seems to try to do is wait until the button is pressed, and then execute some code. That functionality is already provided by the event management system in JavaFX (and the same is true for any UI toolkit): just execute the code in the event handler.

(As an aside, your use of wait() is incorrect, and if you fix that, the thread will never wake up because you are not calling notifyAll() on the same object on which you are calling wait() .)

You can achieve what you seem to be trying to do simply with

package net.jpajavafx;
import javafx.event.ActionEvent;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.fxml.FXML;
import java.util.logging.*;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

public class MainController {

    @FXML
    private TextArea textarea;
    @FXML
    private TextField textfield;

   Variablesstoring stock = new Variablesstoring();
    
    public void ok(ActionEvent event) {
        String getValue = textfield.getText();
        stock.setEntrystr(getValue);          //here i have something to put in an Int, I put it aside to reduce the length
        textfield.setText("");
        processInput();
    }
    
    public void processInput() {
        int etat = stock.getEntrystr();
        switch (etat) {
        case 1:
            //runs a method
            break;
        default:
            break;
        }   
    }
}

You have to start another thread using a Runnable , so your UI thread does not get blocked while the save-operation completes.

You can do this by placing a listener on the button that will start the save-operation on a new thread when the button is clicked. The code for adding a listener to a button that starts a new thread would look something like this:

//Creating the mouse event handler 
  EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() { 
     @Override 
     public void handle(MouseEvent e) { 
     MainController controller = new MainController();
     controller.start();
     } 
  };  
//Registering the event filter 
button.addEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler);   

The code you posted doesn't really do anything. Your call to waitinput() only logs and calls wait() . wait() is not what you want, since this operation is intended for putting a thread on hold until it is notified, not for executing a task in a seperate thread. Remove the obj.wait() , and add a listener that calls your logging method when the button is clicked. Also, get rid of the while-loop. The EventHandler will take care of events in the background.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM