Изменить цвет кругов javafx в определенное время, используя многопоточность - PullRequest
0 голосов
/ 01 октября 2018

Я создаю симулятор светофора с javafx, который меняет цвет каждые 2 секунды (первый красный свет мигает и остается в течение 2 секунд), используя концепцию многопоточности.У меня есть код, указанный ниже.Но это не работает, как ожидалось.Он просто мигает и гаснет. Может ли кто-нибудь помочь мне понять, где я ошибся?Спасибо

public void startThreads() throws InterruptedException {

    Runnable taskOne = new Runnable(){
        @Override
        public void run(){              
            try {
                Platform.runLater(new Runnable() {
                    @Override 
                    public void run() {
                        circle.setFill(Color.RED);
                        circle1.setFill(Color.GREY);
                        circle2.setFill(Color.GREY);
                    }
                  });
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    Runnable taskTwo ......

    Runnable taskThree .....

    Thread thread1 = new Thread(taskOne);
    Thread thread2 = new Thread(taskTwo);
    Thread thread3 = new Thread(taskThree);

    //Start thread 1
    thread1.start();
    thread1.join();

    //start thread 2
    thread2.start();
    thread2.join();

    //Start thread 3
    thread3.start();
    thread3.join();
}

Ответы [ 3 ]

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

Я был так озадачен тем, как заставить это работать честно. Я согласен с Седриком проверить класс JavaFX Animation, но мне было скучно, поэтому я сделал эту работу, и определенно есть лучшие способы сделать это, но я приложил все усилия, чтобы попытатьсясохраняйте как можно больше кода, потому что вы хотели от этого отказаться.Просто посмотрел на это снова его p̶r̶e̶t̶t̶y̶ ̶m̶u̶c̶h̶ только имена переменных lol

public class Main extends Application {

    private Circle circle;
    private Circle circle1;
    private Circle circle2;
    private HashMap<Circle,Color> colorHashMap = new HashMap<>();
    private HashMap<Circle,Integer> counterHashMap = new HashMap<>();

    @Override
    public void start(Stage stage) {
        circle = new Circle(15, 15,30, Color.GREEN);
        colorHashMap.put(circle,Color.GREEN);
        counterHashMap.put(circle, 3);//Start On

        circle1 = new Circle(15, 45,30, Color.GREY);
        colorHashMap.put(circle1,Color.YELLOW);
        counterHashMap.put(circle1, 2);

        circle2 = new Circle(15, 60,30, Color.GREY);
        colorHashMap.put(circle2,Color.RED);
        counterHashMap.put(circle2, 1);

        VBox vBox = new VBox();
        vBox.getChildren().addAll(circle,circle1,circle2);

        Scene scene = new Scene(vBox);
        stage = new Stage();
        stage.setScene(scene);
        stage.show();

        try {
            startThreads();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void startThreads() throws InterruptedException {
        new Thread(()->{
            while (true) {
                flipColor(circle);
                flipColor(circle1);
                flipColor(circle2);

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void flipColor(Circle circle){
        if(counterHashMap.get(circle)%3==0) {
            Platform.runLater(()->circle.setFill(colorHashMap.get(circle)));
            counterHashMap.put(circle,1);
        }
        else {
            if(!circle.getFill().equals(Color.GREY))
                Platform.runLater(()->circle.setFill(Color.GREY));
            counterHashMap.put(circle,counterHashMap.get(circle)+1);
        }

    }

    public static void main(String[] args) { launch(args); }
}
0 голосов
/ 01 октября 2018

Вот MCVE , который использует Временная шкала .Чтобы получить различную продолжительность, используйте пример @fabian Timeline.Этот пример имеет длительность 2 секунды для всех источников света.

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 *
 * @author blj0011
 */
public class TrafficLightsFX extends Application
{

    String currentLight = "GREEN";

    @Override
    public void start(Stage primaryStage)
    {
        //Light GUI
        //https://www.color-hex.com/color-palette/35021
        String COLOR_GREEN_DARK = "#008000";
        String COLOR_GREEN = "47C746";
        String COLOR_YELLOW_DARK = "CA7602";
        String COLOR_YELLOW = "FFFF40";
        String COLOR_RED_DARK = "A30504";
        String COLOR_RED = "FF0000";

        Circle red = new Circle(25, Color.valueOf(COLOR_RED_DARK));
        Circle green = new Circle(25, Color.valueOf(COLOR_GREEN_DARK));
        Circle yellow = new Circle(25, Color.valueOf(COLOR_YELLOW_DARK));

        VBox trafficLight = new VBox(red, yellow, green);

        Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(2), (ActionEvent event) -> {
            switch (currentLight) {
                case "GREEN":
                    red.setFill(Color.valueOf(COLOR_RED_DARK));
                    green.setFill(Color.valueOf(COLOR_GREEN));
                    currentLight = "YELLOW";
                    break;
                case "RED":
                    yellow.setFill(Color.valueOf(COLOR_YELLOW_DARK));
                    red.setFill(Color.valueOf(COLOR_RED));
                    currentLight = "GREEN";
                    break;
                case "YELLOW":
                    green.setFill(Color.valueOf(COLOR_GREEN_DARK));
                    yellow.setFill(Color.valueOf(COLOR_YELLOW));
                    currentLight = "RED";
                    break;
            }
        }));
        timeline.setCycleCount(Timeline.INDEFINITE);

        Button btn = new Button();
        btn.setText("Start");
        btn.setOnAction((ActionEvent event) -> {
            switch (timeline.getStatus()) {
                case STOPPED:
                case PAUSED:
                    timeline.play();
                    break;
                case RUNNING:
                    timeline.pause();
                    break;
            }
        });

        VBox root = new VBox(new StackPane(trafficLight), btn);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

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

С Javadoc Thread.join

Ожидает смерти этой нити.

Это означает

thread1.start();
thread1.join();

не дает никаких преимуществ по сравнению с

taskOne.run();

, поскольку это останавливает выполнение метода, вызывающего join, до тех пор, пока Thread не завершится.


Возможнодобейтесь того, что вы пытаетесь сделать, более элегантным способом, используя Timeline:

Timeline timeline = new Timeline(
    new KeyFrame(Duration.ZERO, evt -> {
        circle.setFill(Color.RED);
        circle1.setFill(Color.GREY);
        circle2.setFill(Color.GREY);
    }),
    new KeyFrame(Duration.seconds(2), evt -> {
        // TODO: GUI modifications for second state
    }),
    new KeyFrame(Duration.seconds(4), evt -> {
        // TODO: GUI modifications for third state
    })
);
timeline.play();

. Возможно, вам придется настроить длительность для третьего KeyFrame.Параметр Duration указывает время с начала анимации .EventHandler<ActionEvent> выполняются в потоке приложения JavaFX и не должны содержать долго выполняющийся код, такой как Thread.sleep.Возможно, вам придется добавить дополнительные KeyFrame с.

...