This discussion is archived
2 Replies Latest reply: Apr 16, 2013 11:09 AM by KonradZuse RSS

DateTimeFormatter bug?? with multiple instances of DateTimeFormatter

KonradZuse Explorer
Currently Being Moderated
Okay so I basically use 1 instance of LocalTime.now() and set is as clock. From there I have 3 different Formatters
    DateTimeFormatter a = DateTimeFormatter.ofPattern("a");
    DateTimeFormatter h = DateTimeFormatter.ofPattern("h:mm");
    DateTimeFormatter s = DateTimeFormatter.ofPattern("ss");
    
I think add each to a label
        labelP = new Label(a.format(clock));
        labelH = new Label(h.format(clock));
        labelS = new Label(s.format(clock));
and update it using
 public void clock()
    {
   
        
        Timeline countdown = new Timeline(
                
                 new KeyFrame(javafx.util.Duration.ZERO,
                ((event)->  
                {
                clock = LocalTime.now();
            
                labelS.setText(s.format(clock));
                                labelH.setText(h.format(clock));
                                                labelP.setText(a.format(clock));
                //seconds.set(LocalTime.now().getSecond());
                //seconds.set(LocalTime.now().getSecond());
                }
                
                )),
                new KeyFrame(javafx.util.Duration.seconds(1)));

          countdown.setCycleCount(Timeline.INDEFINITE);
          countdown.play();  
    }
Now originally the first format was ("ss:a") and when that happened only that label displayed seconds, but when removed, the other label with("ss") started to function.

Now the ("ss") label is the only one that functions correctly. The hour/minute label will not update unless I do something weird. If I, for example, alt tab into my full screen game called Heroes of Newerth it will update the minutes/hours right there. When I had both ss labels, the first one updated like normal, and the second one would update when I would alt tab in and out of that game.

It seems as if it can handle multiple formats, but something with it's updating is funky. I don't think it's the animation class since it changes when I switch the values in the formatter...

THoughts?
  • 1. Re: DateTimeFormatter bug?? with multiple instances of DateTimeFormatter
    James_D Guru
    Currently Being Moderated
    This works fine for me:
    package fx8tests;
    
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;
    import javafx.animation.Animation;
    import javafx.animation.KeyFrame;
    import javafx.animation.Timeline;
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    import javafx.util.Duration;
    
    public class Clock extends Application {
        
        @Override
        public void start(Stage primaryStage) {
            
            VBox root = new VBox(5);
            final Label labelP = new Label();
            final Label labelH = new Label();
            final Label labelS = new Label();
            root.getChildren().addAll(labelP, labelH, labelS);
            
            final DateTimeFormatter a = DateTimeFormatter.ofPattern("ss:a");
            final DateTimeFormatter h = DateTimeFormatter.ofPattern("h:mm");
            final DateTimeFormatter s = DateTimeFormatter.ofPattern("ss");
            Timeline clockwork = new Timeline(
                    new KeyFrame(Duration.ZERO,
                        event -> {
                           LocalTime clock = LocalTime.now();
                           labelP.setText(a.format(clock));
                           labelH.setText(h.format(clock));
                           labelS.setText(s.format(clock));
                        }
                    ),
                    new KeyFrame(Duration.seconds(1))
            );
            clockwork.setCycleCount(Animation.INDEFINITE);
            clockwork.play();
            
            Scene scene = new Scene(root, 300, 250);
            
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    (OK, I haven't actually tested whether or not the am/pm clicks over correctly, but I'd have to wait a few hours for that. Both labels displaying seconds update, and the minutes update.)

    If the formatter is producing the correct format, it's working. Updating, and the user interface display, has nothing to do with the DateTimeFormatter class, and since you see the updated time when you do something involving the UI I think you can assume that class is working correctly. So there is either a bug in the timeline/keyframe classes, or in your code...
  • 2. Re: DateTimeFormatter bug?? with multiple instances of DateTimeFormatter
    KonradZuse Explorer
    Currently Being Moderated
    It works when I do LocalTime clock2 = new LocalTime.now(); instead of clock = LocalTime.now();

    However I just had it run for another minute and it took a couple of seconds before the minute updated... >(

    then after another min it does nothing
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    
    import java.time.Duration;
    import java.time.Instant;
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;
    import javafx.animation.Animation.Status;
    import javafx.animation.KeyFrame;
    import javafx.animation.Timeline;
    import javafx.application.Application;
    import javafx.beans.binding.Bindings;
    import javafx.beans.property.BooleanProperty;
    import javafx.beans.property.IntegerProperty;
    import javafx.beans.property.SimpleBooleanProperty;
    import javafx.beans.property.SimpleIntegerProperty;
    import javafx.event.ActionEvent;
    import javafx.event.Event;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.effect.Blend;
    import javafx.scene.effect.BlendMode;
    import javafx.scene.effect.DropShadow;
    import javafx.scene.effect.InnerShadow;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.paint.Color;
    import javafx.scene.text.Font;
    import javafx.scene.text.FontWeight;
    import javafx.stage.Stage;
    import javafx.stage.StageStyle;
    
    /**
     *
     * @author Konrad
     */
    public class Timer extends Application
    {
        Scene scene;
        Stage stage;
        Group root;
    
        Long l;
        
        Label labelH,labelS,labelT,labelP;
        Button button;
    
        LocalTime clock = LocalTime.now();
        DateTimeFormatter a = DateTimeFormatter.ofPattern("a");
        DateTimeFormatter h = DateTimeFormatter.ofPattern("h:mm");
        DateTimeFormatter s = DateTimeFormatter.ofPattern("ss");
        
        Duration duration = Duration.ofSeconds(6);
        
        IntegerProperty seconds = new SimpleIntegerProperty();
        BooleanProperty bool = new SimpleBooleanProperty();
        
        Image button1 = new Image(getClass().getResourceAsStream("button1.png"));
        Image button2 = new Image(getClass().getResourceAsStream("button2.png"));
        Image button3 = new Image(getClass().getResourceAsStream("button.gif"));
        
        Image body1 = new Image(getClass().getResourceAsStream("body1.png"));
        Image body2 = new Image(getClass().getResourceAsStream("body2.png"));
        
        ImageView imageV = new ImageView(body1);
        
        DropShadow ds = new DropShadow(1,2,2,Color.RED);
       InnerShadow is = new InnerShadow(1,1,1,Color.ORANGE);
       
      // Blend blend = new Blend(BlendMode.OVERLAY,ds,is);
       Blend blend = new Blend(BlendMode.ADD,ds,is);
       
       
    
        
        
        double x, y;
    
    
        @Override
        public void start(Stage stage)
        {
            
            this.stage = stage;
            configureGroup();
            configureScene();
            configureStage();
            mouseEvents();
           // myLayout();
        }
        
        public void configureGroup()
        {
            label();
            button();    
            clock();
    
            root = new Group(button,imageV,labelP,labelS,labelH,labelT);
        }
    
        public void button()
        {
            button = new Button("",new ImageView(button1));
            button.setStyle("-fx-background-color: null;");
            button.setLayoutX(-10);
            
            
           button.setOnMouseEntered((event)
                   ->{
               button.setGraphic(new ImageView(button3));
               event.consume();
                     });
                           
                    button.addEventFilter(MouseEvent.MOUSE_EXITED,(event)
                            ->{
                        
                        if(button.isArmed())
                        {
                            button.setGraphic(new ImageView(button2));
                        }
                        else
                        {
                            button.setGraphic(new ImageView(button1));
                        }
                            event.consume();
                    });
              
                    
    
    button.addEventHandler(MouseEvent.MOUSE_PRESSED, (event)
            ->{ 
                button.setGraphic(new ImageView(button2));
                imageV.setImage(body2);
                button.setMouseTransparent(true);
                timer();
                event.consume();
                
              });
                    
                   
        
                        
        }
        
        public void label()
        {
           // seconds.set(LocalTime.now().getSecond());
    
    //clock = clock.minusHours(5);
            labelP = new Label(a.format(clock));
            labelH = new Label(h.format(clock));
            labelS = new Label(s.format(clock));
            labelT = new Label();
            
            
            labelP.setEffect(blend);
            labelH.setEffect(blend);
            labelS.setEffect(blend);
            labelT.setEffect(blend);
    
            labelP.setLayoutX(180);
            labelH.setLayoutX(110);
            labelS.setLayoutX(320);
            labelT.setLayoutX(260);
            
            labelP.setLayoutY(110);
            labelH.setLayoutY(220);
            labelS.setLayoutY(220);
            labelT.setLayoutY(337);
            
            labelP.setFont(Font.font(null, FontWeight.BOLD, 20));
            labelH.setFont(Font.font(null, FontWeight.BOLD, 30));
            labelS.setFont(Font.font(null, FontWeight.BOLD, 30));
            labelT.setFont(Font.font(null, FontWeight.BOLD, 30));
            
              labelT.textProperty().bind(
                        Bindings.when(seconds.greaterThan(0))
                        .then(Bindings.format(" %d", seconds))
                        .otherwise("")); 
              
            
              labelS.visibleProperty().bind(seconds.isEqualTo(0));
              labelH.visibleProperty().bind(seconds.isEqualTo(0));
        }
        public void clock()
        {
       
            
            Timeline countdown = new Timeline(
                    
                     new KeyFrame(javafx.util.Duration.ZERO,
                    ((event)->  
                    {
                    LocalTime clock2 = LocalTime.now();
                
                    labelS.setText(s.format(clock2));
                                    labelH.setText(h.format(clock2));
                                                    labelP.setText(a.format(clock2));
                    //seconds.set(LocalTime.now().getSecond());
                    //seconds.set(LocalTime.now().getSecond());
                    }
                    
                    )),
                    new KeyFrame(javafx.util.Duration.seconds(1)));
    
              countdown.setCycleCount(Timeline.INDEFINITE);
              countdown.play();  
        }
       public void timer()
        {
    
              Timeline countdown = new Timeline(
                   new KeyFrame(javafx.util.Duration.ZERO,
                                        (event) ->  seconds.set((int) duration.getSeconds()))
                    ,
                   new KeyFrame(javafx.util.Duration.seconds(1),                         
                                        (event) -> duration = duration.minusSeconds(1))
                                                        
              );
              countdown.setCycleCount((int)duration.getSeconds());
              countdown.play();
                    
                    countdown.setOnFinished((event) -> 
                    {
                                            System.out.println("kaw");
                                            seconds.set((int) duration.getSeconds());
                                    button.setGraphic(new ImageView(button1));
                                    button.setMouseTransparent(false);
                                    duration = duration.plusSeconds(6);
                imageV.setImage(body1);
                    });
           
        }
        public void configureScene()
        {
            scene = new Scene(root, 500,500,true);
            scene.setFill(Color.TRANSPARENT);
        }
        
        public void configureStage()
        {
            stage.initStyle(StageStyle.TRANSPARENT);
            stage.setTitle("Countdown Timer");
            stage.setResizable(false);
           // stage.setHeight(SCENE_HEIGHT);
            //stage.setWidth(SCENE_WIDTH);
            stage.centerOnScreen();
            stage.setScene(scene);
            stage.show();
        }
        public void mouseEvents()
        {
            root.setOnMousePressed((MouseEvent me)
          ->{
                x = me.getScreenX() - stage.getX();
                y = me.getScreenY() - stage.getY();
    
                me.consume();
            });
            root.setOnMouseDragged((MouseEvent me) ->
            {
                stage.setX(me.getScreenX() - x);
                stage.setY(me.getScreenY() - y);
                me.consume();
            });
    
        }
    
    
        /**
         * The main() method is ignored in correctly deployed JavaFX application.
         * main() serves only as fallback in case the application can not be
         * launched through deployment artifacts, e.g., in IDEs with limited FX
         * support. NetBeans ignores main().
         *
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            Application.launch(args);
        }
    }
    Edited by: KonradZuse on Apr 4, 2013 1:30 PM

    I realize that if I scroll over the button both will start ticking again.... I tried to initiate clock() after setting the root, but it still has issues.... Will update.

    Edited by: KonradZuse on Apr 4, 2013 1:42 PM

    After turning off the event for mouse entering/exiting scrolling over the button does nothing to the time. It makes me wonder if an event is what is triggering it to move again, but why isn't it working within it's own event...........

    Edited by: KonradZuse on Apr 7, 2013 7:27 PM

    Issue still exists. JamesD if you see this can you please check and see if it's me, or the code, or what? :P

    Edited by: KonradZuse on Apr 16, 2013 11:08 AM

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points