Change javafx circles color in certain time using multithreads

前端 未结 3 532
情深已故
情深已故 2021-01-27 18:45

I am creating traffic light simulator with javafx that changes colour in every 2 seconds (first red light blinks and remain for 2 seconds) using the concept of multithreading. I

相关标签:
3条回答
  • 2021-01-27 19:19

    I was so confused on how to make this work honestly I agree with Sedrick check out the JavaFX Animation class but I was bored so I made this work also there is definitely better ways to do this but I did my best to try and keep as much code as possible because you wanted to lean from this. Just looked at this again its p̶r̶e̶t̶t̶y̶ ̶m̶u̶c̶h̶ only the variable names 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 讨论(0)
  • 2021-01-27 19:34

    From the javadoc of Thread.join

    Waits for this thread to die.

    This means

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

    doesn't provide any benefits compared to

    taskOne.run();
    

    since this stops the execution of the method invoking join until the Thread completes.


    It's possible to achieve what you're trying to do in a much more elegant way by using 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();
    

    You may need to adjust the duration for the third KeyFrame. The Duration parameter specifies the time from the beginning of the animation. The EventHandler<ActionEvent>s are executed on the JavaFX application thread and must not contain long-running code such as Thread.sleep. You may need to add additional KeyFrames.

    0 讨论(0)
  • 2021-01-27 19:37

    Here is an MCVE that uses Timeline. To get different durations use @fabian Timeline example. This example has a 2-second duration for all lights.

    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 讨论(0)
提交回复
热议问题