Search code examples
javamultithreadingjavafxjavafx-8fxml

Java FX How to 'Stop' Thread Midway and Restart it or destroy it


Can't stop Thread Midway and Restart add Node Thread.

This is what i getting

enter image description here

This is what i need I want something like this over and over whenever i press Refresh Button

clean screen and Restart (for example. A to N In proper order )

enter image description here

Why? So i can choice different List before refresh.

Back Story (ignore) I'm working on a little project on JavaFX from a month now but this problem is bugging me. I did my research and try to figure it out but nothing. I really appreciated if someone guild me on the right path. Please highlight this question so others don't have to waste so much time

I have JavaFX Controller

@FXML public FlowPane flow_panel;

MyPlatform mp = new MyPlatform(); // A class that implements Runnable
Thread t;

boolean first_time_click = true; // To check Whether i clicked '1st' time or 'second' time
@FXML
private void Refresh_Btn(ActionEvent event) 
{       
    System.out.println("Refresh btn");

     t = new Thread(mp); //Creating Thread object

    if(first_time_click == true) { first_time_click = false;



        MyPlatform.stop = false; //Thread object.Stop, When false do nothing

        flow_panel.getChildren().clear(); // cleaning screen
        System.out.println("Start Thread");
        t.setDaemon(true);  
        t.start(); //Start Thread


    } else if(first_time_click == false){   first_time_click = true;



        MyPlatform.stop = true; //Exist loop
        t.interrupt(); // I thought   't.interrupt()'   it work but nothing
        System.out.println("Stop Thread");

        flow_panel.getChildren().clear(); // cleaning screen
        MyPlatform.stop = false; //Thread object.Stop, When false do nothing
        t.setDaemon(true);
        t.start(); //Start Thread
        System.out.println("Stoped  Thread Started again");


    } 

}

Then i have a class named MyPlatform that implements Runnable

import javafx.application.Platform;
import javafx.scene.control.Button;
import setups.WindowSetupConfig;

public class MyPlatform implements Runnable
{   

public static boolean stop = false;

@Override
public void run()
{



    for (String name : ListOfNames.getlist()) 
    {
        if(stop)    // Exit for loop if true
        {
            break;
        }
        Platform.runLater(new Runnable()
        {

            @Override
            public void run()
            {   

                Button btn = new Button("Button : "+name);

                System.out.println(name);


        //Adding that button to FlowPane
        WindowSetupConfig.getController().flow_panel.getChildren().add(btn);
                }
            });

            try {
                Thread.sleep(1000); // Wait for 1 sec, Controlling speed
            } catch (InterruptedException e) { // try catch it needed for some reason
                e.printStackTrace();
            }

        }


    }

}

I hava a list of string. Orignally that list would have over 500 names

import java.util.ArrayList;

public class ListOfNames
{   
    private static ArrayList<String> list_of_names ;

    public ListOfNames()
    {
        list_of_names = new ArrayList<>();
        list_of_names.add("A");
        list_of_names.add("B");
        list_of_names.add("C");
        list_of_names.add("D");
        list_of_names.add("E");
        list_of_names.add("F");
        list_of_names.add("G");
        list_of_names.add("H");
        list_of_names.add("I");
        list_of_names.add("J");
        list_of_names.add("K");
        list_of_names.add("L");
        list_of_names.add("M");
        list_of_names.add("N");
    }


    public static ArrayList<String> getlist() {
        return list_of_names;
    }
}

Whenever i press Refresh button i want to stop thread midway of adding nods to flow panel. enter image description here

Clean the FlowPane using flow_panel.getChildren().clear(); And restart over from start of the list

enter image description here

Bacially -Stop -Clean -Restart

If there any way to do it with Service or task that would be great


Solution

  • I found Solution to my problem. Now my question is there any better way to achieve the same result Because I'm getting and yellow warring which means I'm doing it the wrong way

    enter image description here

    Luncher.java

        package project;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    public class Luncher extends Application
    {
    
    
        @Override
        public void start(Stage primaryStage) {
            try {
    
    
                Parent root = FXMLLoader.load(getClass().getResource("Window.fxml"));
    
                Scene scene = new Scene(root);          
    
                primaryStage.setScene(scene);
                primaryStage.show();
    
            } catch(Exception e) {
                System.err.println("Luncher Failed !" +e);
            }
        }
    
        public static void main(String[] args) 
        {
    
            launch(args);
    
        }
    
    }
    

    Controller.java

    package project;
    
    
    import java.net.URL;
    import java.util.ResourceBundle;
    
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.layout.FlowPane;
    
    
    public class Controller implements Initializable
    {
    
    
        @FXML
        public FlowPane flowPane;
    
    
        //A class that implements  Runable, So i can start a thead there
        private MyRunableClass my_run_class; 
        private Thread t; //Thread object
    
        @Override
        public void initialize(URL location, ResourceBundle resources)
        {       
            new ListOfNames(); //Init list of names and creating Array list, In real program i will get this list from database
            my_run_class = new MyRunableClass(this);
    
        }
    
    
    
    
    
        @FXML
        void clear_Button(ActionEvent event) 
        {
            flowPane.getChildren().clear(); 
        }
    
    
        @FXML
        void start_Button(ActionEvent event) 
        {   
            t = new Thread(my_run_class);
            t.start();
        }
    
        @FXML
        void stop_Button(ActionEvent event) {
            t.suspend(); ///NOT WORKING???????? any way to stop running thread
        }
    
    
    
    
        private boolean firstTime_thread_running = true; // To check Whether i clicked '1st' time or 'second' time
    
        @FXML
        void refresh_Button(ActionEvent event) 
        {
    
    
            if(firstTime_thread_running == false){
    
    
                //Stop
                //  my_run_class.stop = true; //Exist loop
                t.suspend();
                System.out.println("Suspend");
    
            } else
            {   
                firstTime_thread_running = false;
            }
    
    
    
    //Clean
                flowPane.getChildren().clear(); // cleaning screen
                System.out.println("Screen clear");
    
    
    //Restart , well.. at least that what i want
                t = new Thread(my_run_class);
                t.setDaemon(true);
                t.start(); //Start Thread
                System.out.println("Stoped  Thread Started again"); 
    
        }
    
    
    
    }
    

    MyRunableClass.java

        package project;
    
    import javafx.application.Platform;
    import javafx.scene.control.Button;
    
    public class MyRunableClass implements Runnable
    {       
        private Controller controller;
    
        public MyRunableClass(Controller controller)
        {   
            //Getting FXML Controller
            this.controller = controller;
        }
    
    //  public boolean stop = false;
    
        @Override
        public void run()
        {
    
    
    
            for (String name : ListOfNames.getlist()) 
            {
    //          if(stop)    // Exit for loop if true
    //          {
    //              break;
    //          }
                Platform.runLater(new Runnable()
                {
    
                    @Override
                    public void run()
                    {   
    
                        Button btn = new Button("Button : "+name);
    
                        System.out.println(name);
    
                        controller.flowPane.getChildren().add(btn);
                    }
                });
    
                try {
                    Thread.sleep(1); // Wait for half sec this time
                } catch (InterruptedException e) { // try catch it needed for some reason
                    e.printStackTrace();
                }
    
            }
    
    
        }
    
    }
    

    ListOfNames.java

        package project;
    
    import java.util.ArrayList;
    
    public class ListOfNames
    {   
        private static ArrayList<String> list_of_names ;
    
        public ListOfNames()
        {
            list_of_names = new ArrayList<>();
            list_of_names.add("A");
            list_of_names.add("B");
            list_of_names.add("C");
            list_of_names.add("D");
            list_of_names.add("E");
            list_of_names.add("F");
            list_of_names.add("G");
            list_of_names.add("H");
            list_of_names.add("I");
            list_of_names.add("J");
            list_of_names.add("K");
            list_of_names.add("L");
            list_of_names.add("M");
            list_of_names.add("N");
            list_of_names.add("O");
            list_of_names.add("P");
            list_of_names.add("Q");
            list_of_names.add("R");
            list_of_names.add("S");
            list_of_names.add("T");
            list_of_names.add("U");
            list_of_names.add("V");
            list_of_names.add("W");
            list_of_names.add("X");
            list_of_names.add("Y");
            list_of_names.add("Z");
    
        }
    
    
        public static ArrayList<String> getlist() {
            return list_of_names;
        }
    }
    

    Window.fxml

        <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.layout.AnchorPane?>
    <?import javafx.scene.layout.FlowPane?>
    
    
    <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="413.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="project.Controller">
       <children>
          <FlowPane fx:id="flowPane" layoutX="2.0" layoutY="61.0" prefHeight="352.0" prefWidth="600.0" style="-fx-border-color: #000000; -fx-border-insets: 1.1; -fx-border-width: 5;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="61.0" />
          <Button layoutX="405.0" layoutY="14.0" mnemonicParsing="false" onAction="#stop_Button" prefHeight="39.0" prefWidth="80.0" text="Stop" />
          <Button layoutX="313.0" layoutY="14.0" mnemonicParsing="false" onAction="#start_Button" prefHeight="39.0" prefWidth="80.0" text="Star" />
          <Button layoutX="497.0" layoutY="14.0" mnemonicParsing="false" onAction="#clear_Button" prefHeight="39.0" prefWidth="80.0" text="Clean" />
          <Button layoutX="40.0" layoutY="14.0" mnemonicParsing="false" onAction="#refresh_Button" prefHeight="39.0" prefWidth="109.0" text="Refresh" />
       </children>
    </AnchorPane>