Java FX Как остановить поток на полпути и перезапустить или уничтожить - PullRequest
0 голосов
/ 25 октября 2018

Не могу остановить поток На полпути и Перезапустить Добавить нить узла.

Это то, что я получаю

enter image description here

Это то, что мне нужно Я хочу что-то подобное снова и снова, когда нажимаю Кнопка обновления

чистый экран и Перезагрузка (например, от A до N В правильном порядке)

enter image description here

Почему? Так что я могу выбрать другой список перед обновлением.

Назад История (игнорировать) Я работаю надмаленький проект на JavaFX уже месяц, но эта проблема меня беспокоит.Я сделал свое исследование и пытаюсь понять это, но ничего.Я очень признателен, если кто-то направит меня на правильный путь.Пожалуйста, выделите этот вопрос, чтобы другим не пришлось тратить так много времени

У меня есть 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");


    } 

}

Затем у меня есть класс с именем MyPlatform, который реализует 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();
            }

        }


    }

}

У меня есть список строк.Изначально этот список содержал бы более 500 имен

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;
    }
}

Всякий раз, когда я нажимаю кнопку Обновить я хочу остановить поток на полпути добавления кивков впанель потока.enter image description here

Очистите FlowPane с помощью flow_panel.getChildren (). Clear (); и перезапустите с начала списка

enter image description here

Bacially -Stop -Clean -Restart

Если есть какой-нибудь способ сделать это с Service или task , это было бы здорово

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Я не прочитал весь ваш код, но я дам общее описание того, как отменить и «перезапустить» Task.

Прежде всего, не используйте suspend, stop или resume методы Thread;по какой-то причине они устарели.

Как и все фоновые задачи, для отмены требуется сотрудничество с разработчиком указанной фоновой задачи.Задача должна в нужное время проверять, отменена ли она, и реагировать соответствующим образом.Обычно это делается путем запроса статуса прерывания текущего Thread, но класс Task наследует более простой в использовании метод isCancelled от FutureTask.

Пример с имитацией длительного запускаработа:

public class MyTask extends Task<Void> {

    @Override
    protected Void call() throws Exception {
        for (int i = 0; i < 10_000; i++) {
            if (isCancelled()) {
                break;
            }
            updateMessage(Integer.toString(i));
            Thread.sleep(1L);
            updateProgress(i, 10_000);
        }
        return null;
    }

}

Вы отменяете Task с помощью метода cancel интерфейса Worker.Обратите внимание на проверку isCancelled на каждой итерации цикла;когда вызывается метод cancel, Task останавливается при первой же возможности.Кроме того, вызов Worker.cancel() (или Future.cancel(true)) прервет Thread, означая, что любая прерываемая операция (например, Thread.sleep) вызовет InterruptedException.

Вы можете реагировать на успешное выполнение, сбой или отмену Task, наблюдая за свойствами Task или добавляя обработчики событий.

MyTask task = new MyTask();
task.setOnSucceeded(event -> handleSucceededTask());
task.setOnFailed(event -> handleFailedTask());
task.setOnCancelled(event -> handleCancelledTask());

Именно в этих обратных вызовахВы можете выполнить очистку и выполнить new Task по мере необходимости.Обратите внимание, что вы должны запустить новый Task, потому что Task предназначен для одноразового использования.

0 голосов
/ 25 октября 2018

Я нашел решение своей проблемы.Теперь мой вопрос, есть ли лучший способ добиться того же результата, потому что я получаю желтую вражду, что означает, что я делаю это неправильно

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...