0

I am designing a customized calculator based on fuel cost and the car's fuel efficiency. I'm unable to run the client as I keep getting this exception "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4 exception". Would really appreciate some help on this!

Server:

public class MiniProjServer extends Application {

    @Override
    public void start(Stage primaryStage) {

        TextArea ta = new TextArea();
       new Thread(() -> {  
          try{

                ServerSocket serverSocket = new ServerSocket(8000);
                Platform.runLater(() ->
                    ta.appendText("Mini Project Server started at " 
                        + new Date() + '\n'));
                Socket socket = serverSocket.accept();
                DataInputStream inputFromClient = new DataInputStream(socket.getInputStream());
                DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
                int getFuelType= inputFromClient.readInt();

                Scanner scanner = new Scanner(new File("fuelCost.csv"));

                //Set the delimiter used in file
                scanner.useDelimiter(",");

                //Get all tokens and store them in some data structure

                String InputLine="";
                while (scanner.hasNextLine()) {
                    InputLine= scanner.nextLine();
                    String[]fuelCostArray=InputLine.split(",");


                    if(getFuelType==1)
                    {
                        outputToClient.writeUTF(fuelCostArray[0]);
                    }
                    else if(getFuelType==2)
                    {
                        outputToClient.writeUTF(fuelCostArray[1]);
                    }

                }
            }  catch (IOException ex) {
                ex.printStackTrace();
            }
















         }).start();


        StackPane root = new StackPane();

        root.getChildren().addAll(ta);
        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Server");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

Client:

public class MiniProject extends Application {
     ServerSocket ss;
     Socket s;
     DataInputStream dis;
     DataOutputStream dos;



    @Override
    public void start(Stage primaryStage) 

    {


        //Create New Image 
        Image image = new Image("/image/alset.PNG");
         //Create image view so that it can be added to Grid Pane
         ImageView alset = new ImageView();
         alset.setImage(image);

        //Title of the project
        Text title= new Text("Alset Business Trip Calculator");
        title.setFont(Font.font("verdana", FontWeight.BOLD, FontPosture.REGULAR, 20));
        Label lblDist = new Label();
        lblDist.setText("Distance:");
        //Textbox to get user input for distance
        TextField TxtDistance = new TextField();
        TxtDistance.setPromptText("Enter distance in miles");
        TxtDistance.setFocusTraversable(false);

         Text TxtDistUnit= new Text("miles");
         TxtDistUnit.setFont(Font.font("verdana", FontWeight.BOLD,10));
         Text TxtFCUnit = new Text("miles per gallon(MPG)");
         TxtFCUnit.setFont(Font.font("verdana", FontWeight.BOLD,10));


        Label lblFuelConsumption = new Label();
        lblFuelConsumption.setText("Fuel Consumption:");
        //Textbox to get user input for Car's fuel efficiency
        TextField TxtFuelConsumption = new TextField();
        TxtFuelConsumption.setPrefWidth(100);
        TxtFuelConsumption.setPromptText("Input Cars fuel consumption in miles per gallon(MPG)");
        TxtFuelConsumption.setFocusTraversable(true);

        Label lblRBTitle = new Label();
        lblRBTitle.setText("Fuel Type:");
        //Radio Button to get Fuel Type
        RadioButton rbOctane = new RadioButton("98 Octane(£1.03/L)");
        RadioButton rbDiesel = new RadioButton("Diesel(£1.05/L)");
        ToggleGroup fuelType = new ToggleGroup();
        rbOctane.setToggleGroup(fuelType);
        rbDiesel.setToggleGroup(fuelType);
        fuelType.selectToggle(rbOctane);
        //Button to calculate the cost of the trip
        Button calcFuelCostBtn = new Button();
        //Button to clear all the user inputs
        Button clearBtn = new Button();
        calcFuelCostBtn.setStyle("-fx-border-color: #ff0000; -fx-border-width: 5px;");

        Label lblResult= new Label();
        lblResult.setText("Cost:£");
        Label lblException = new Label();

        Label lblTest=new Label();

        calcFuelCostBtn.setText("Calculate Fuel Cost");
        clearBtn.setText("Clear");

        TextField TxtResultBox  = new TextField();

           new Thread(() -> {  
             try{


                 s=new Socket("localhost",8000);
                 dis= new DataInputStream(s.getInputStream());
                 dos= new DataOutputStream(s.getOutputStream());
             } catch (IOException ex) {
                 Logger.getLogger(MiniProject.class.getName()).log(Level.SEVERE, null, ex);
             }




             //Event Handler to set the action when user clicks on "Calculate Fuel Cost" Button
             calcFuelCostBtn.setOnAction(new EventHandler<ActionEvent>() {

                 @Override
                 public void handle(ActionEvent event) {

                     TxtResultBox.clear();
                     //checks if either of the textboxes are empty
                     if(TxtDistance.getText().trim().equals(""))
                     {
                         lblResult.setText("No distance value is entered!");
                     }
                     else if(TxtFuelConsumption.getText().trim().equals(""))
                     {
                         lblResult.setText("No fuel consumption value is entered!");
                     }
                     RadioButton rb = (RadioButton)fuelType.getSelectedToggle();
                     //if Octane Radio Button is selected call calculate octane cost method
                     if(fuelType.getSelectedToggle()==rbOctane)
                     {
                         //Exception handling if user enters an invalid number into each respective textbox
                         try{

                             double distVal= Double.parseDouble(TxtDistance.getText());
                             double fuelConsumpVal= Double.parseDouble(TxtFuelConsumption.getText());
                             int propaneFuelType=1;
                             if(fuelConsumpVal==0)
                             {
                                 Alert alert = new Alert(AlertType.ERROR);
                                 alert.setTitle("Error");
                                 alert.setHeaderText("Unable to calculate trip cost because:");
                                 alert.setContentText("Fuel Efficiency cannot be 0!");
                                 alert.showAndWait();
                             }
                             else{
                                 //Get scanner instance
                                 dos.writeInt(propaneFuelType);


                                 String  propaneCost = dis.readUTF();

                                 TxtResultBox.setText(String.format("%.2f",calcPropaneCost(distVal,fuelConsumpVal,Double.valueOf(propaneCost))));
                                 printResults(distVal,fuelConsumpVal,rbOctane.getText(),calcPropaneCost(distVal,fuelConsumpVal,Double.valueOf(propaneCost)));
                             }
                         }catch(NumberFormatException ex)
                         {
                             Alert alert = new Alert(AlertType.ERROR);
                             alert.setTitle("Error");
                             alert.setHeaderText("Unable to calculate trip cost because:");
                             alert.setContentText("You did not enter a valid number!");
                             alert.showAndWait();
                         }     catch (IOException ex) {
                             Logger.getLogger(MiniProject.class.getName()).log(Level.SEVERE, null, ex);
                         }


                     }


                     // lblException.setText("You did not enter a valid number!");


                     //if Diesel Radio Button is selected call calculate diesel cost method

                     else if(fuelType.getSelectedToggle()==rbDiesel)
                     {
                         //exception handling for when user enters an invalid numbe into either respective text box
                         try{

                             double distVal= Double.parseDouble(TxtDistance.getText());
                             double fuelConsumpVal= Double.parseDouble(TxtFuelConsumption.getText());
                             int dieselFuelType=2;
                             if(fuelConsumpVal==0)
                             {
                                 Alert alert = new Alert(AlertType.ERROR);
                                 alert.setTitle("Error");
                                 alert.setHeaderText("Unable to calculate trip cost because:");
                                 alert.setContentText("Fuel Efficiency cannot be 0!");
                                 alert.showAndWait();
                             }
                             else{
                                 dos.writeInt(dieselFuelType);


                                 String  dieselCost = dis.readUTF();

                                 //Get all tokens and store them in some data structure
                                 //I am just printing them



                                 TxtResultBox.setText(String.format("%.2f",calcDieselCost(distVal,fuelConsumpVal,Double.valueOf(dieselCost))));
                                 printResults(distVal,fuelConsumpVal,rbDiesel.getText(),calcPropaneCost(distVal,fuelConsumpVal,Double.valueOf(dieselCost)));



                             }
                         }
                         catch(NumberFormatException ex)
                         {
                             Alert alert = new Alert(AlertType.ERROR);
                             alert.setTitle("Error");
                             alert.setHeaderText("Unable to calculate trip cost because:");
                             alert.setContentText("You did not enter a valid number!");
                             alert.showAndWait();

                         }     catch (IOException ex) {
                             Logger.getLogger(MiniProject.class.getName()).log(Level.SEVERE, null, ex);
                         }
                     }


                 }








             });
             //logic behind clear button
             clearBtn.setOnAction(new EventHandler<ActionEvent>() {

                 @Override
                 public void handle(ActionEvent event) {
                     TxtDistance.clear();
                     TxtFuelConsumption.clear();
                     fuelType.selectToggle(null);
                     TxtResultBox.clear();
                 }
             });

             //create new grid pane
             GridPane grid = new GridPane();
             //add all the nodes to grid pane
             grid.getChildren().addAll(title,lblDist,TxtDistance,TxtDistUnit,lblFuelConsumption,TxtFuelConsumption,TxtFCUnit,lblRBTitle,rbOctane,rbDiesel,calcFuelCostBtn,clearBtn,lblResult,lblException,TxtResultBox,alset,lblTest);

             //put each respective nodes into a row and column
             GridPane.setConstraints(alset,0,0,2,1);
             GridPane.setConstraints(title,0,1,2,1);
             GridPane.setConstraints(lblDist,0,3);
             GridPane.setConstraints(TxtDistance,1,3);
             GridPane.setConstraints(TxtDistUnit, 2, 3);
             GridPane.setConstraints(lblFuelConsumption,0,4);
             GridPane.setConstraints(TxtFuelConsumption, 1, 4);
             GridPane.setConstraints(TxtFCUnit, 2, 4);
             GridPane.setConstraints(lblRBTitle,0,5);
             GridPane.setConstraints(rbOctane, 0, 6);
             GridPane.setConstraints(rbDiesel, 1, 6);
             GridPane.setConstraints(calcFuelCostBtn, 0, 7);
             GridPane.setConstraints(clearBtn, 1, 7);
             GridPane.setConstraints(lblResult, 0, 8);
             GridPane.setConstraints(lblException, 0, 9);
             GridPane.setConstraints(TxtResultBox, 1, 8);
             GridPane.setConstraints(lblTest, 1, 10);









             Scene scene = new Scene(grid, 600, 300);

             primaryStage.setTitle("ALSET BUSINESS TRIP CALCULATOR");
             primaryStage.setScene(scene);
             primaryStage.show();

         }).start()
                 ;
                  }


    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
        //method to calculate trip using propane
    public double calcPropaneCost(double distance,double fuelConsumption,double cost) 
    {
        // final double propane_cost=1.03;
         final double gallon_to_litre=3.78541;
         double octaneCost= (distance/fuelConsumption)*gallon_to_litre*cost;


         return octaneCost;
    }    







    //method to calculate trip cost using diesel
    public double calcDieselCost(double distance, double fuelConsumption,double cost)
    {
           final double gallon_to_litre=3.78541;
          // final double diesel_cost=1.05;
           double dieselCost= (distance/fuelConsumption)*gallon_to_litre*cost;
           return dieselCost;
    }

    public void printResults(double distance, double MPG, String fuelType, double result) throws IOException
    {
        try(FileWriter fw = new FileWriter("output.csv",true)){
            StringBuilder sb = new StringBuilder();

            sb.append(distance+",");
            sb.append(MPG+",");
            sb.append(fuelType+",");
            sb.append(result+"\n");

            fw.write(sb.toString());
        }catch(FileNotFoundException ex){
            Alert alert = new Alert(AlertType.ERROR);
            alert.setTitle("Error");
            alert.setHeaderText("An error has occured because:");
            alert.setContentText("The csv file does not exist!");
            alert.showAndWait();

        }
    }


}

Exception:

Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
    at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
    at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:444)
    at javafx.stage.Stage.setScene(Stage.java:251)
    at miniproject.MiniProject.lambda$start$0(MiniProject.java:312)
    at java.lang.Thread.run(Thread.java:748)
  • the error tells it all ;) you __must not__ change any property of a node that's in an active scenegraph off the fx application thread. Simply don't and all is well (btw, there are bunches of similar QAs here on SO - please do at least a bit of research before posting a question ...) – kleopatra Apr 03 '20 at 08:53
  • @kleopatra sorry can you please be more specific by that you mean you must not change any property of the node. I've read that I should use Platform.runLater(() ->...Fairly new to this so I would appreciate some clarity – Sujay Shrestha Apr 03 '20 at 10:29
  • Your `calcFuelCostBtn.setOnAction(/* lots of code*/);` is being run in your background thread. That's causing the exception, because, as stated previously, you must not change any property of an active node in a background thread. It's pointless too, because the event handler itself will be executed on the FX Application thread anyway. Just move that out of the background thread. – James_D Apr 03 '20 at 11:44
  • 1
    Does this answer your question? [How to avoid Not on FX application thread; currentThread = JavaFX Application Thread error?](https://stackoverflow.com/questions/21083945/how-to-avoid-not-on-fx-application-thread-currentthread-javafx-application-th) – M. S. Apr 03 '20 at 13:16

0 Answers0