1 00:00:00,263 --> 00:00:04,593 [MUSIC] 2 00:00:04,593 --> 00:00:08,497 Our time tracking app isn't very good if we don't change the big block of 3 00:00:08,497 --> 00:00:10,070 time, right? 4 00:00:10,070 --> 00:00:13,140 So, there are a couple of ways that we can tackle the problem 5 00:00:13,140 --> 00:00:14,590 of making our clock start ticking. 6 00:00:15,700 --> 00:00:19,370 I think the one that makes the most sense, is to use timeline animation. 7 00:00:20,590 --> 00:00:24,230 Have you ever seen one of those flip books where there's a still picture on one page. 8 00:00:24,230 --> 00:00:28,237 Maybe a stick figure going, and then on the next page he's like, and 9 00:00:28,237 --> 00:00:31,320 then almost the same one on each different pages. 10 00:00:31,320 --> 00:00:33,180 And then it goes kinda go like this. 11 00:00:33,180 --> 00:00:37,260 And if you take the corner and flip the pages, it makes it seem like it's moving. 12 00:00:37,260 --> 00:00:40,450 This is animation in a nutshell, and those are some sweet moves too, huh? 13 00:00:42,060 --> 00:00:46,290 JavaFX provides different powerful types of animation, and 14 00:00:46,290 --> 00:00:48,490 I've linked to some fun examples in the teacher's notes. 15 00:00:49,750 --> 00:00:53,100 So what we are going to do is make a pretty boring flip book. 16 00:00:53,100 --> 00:00:56,388 On each page, we're going to have the remaining time and 17 00:00:56,388 --> 00:00:58,455 every second we'll flip the page. 18 00:00:58,455 --> 00:01:00,990 So, we'll start with 25. 19 00:01:00,990 --> 00:01:01,870 Wait a second. 20 00:01:01,870 --> 00:01:05,550 Flip the page, and it will say 24:59 seconds, etc. 21 00:01:06,850 --> 00:01:11,360 JavaFX provides a pretty straightforward way to accomplish this task. 22 00:01:11,360 --> 00:01:13,030 So let's go learn all about the timeline. 23 00:01:14,880 --> 00:01:19,240 All right, so the first thing that we need to do is create a timeline object. 24 00:01:19,240 --> 00:01:21,270 Let's add a private field to store it. 25 00:01:21,270 --> 00:01:25,991 So we'll put it up here and say, private TimeLine, and 26 00:01:25,991 --> 00:01:32,065 we'll call it mTimeLine. 27 00:01:32,065 --> 00:01:37,445 Now, every time that we prepare an attempt to run, we'll just make a new timeline. 28 00:01:37,445 --> 00:01:38,065 So let's do that. 29 00:01:38,065 --> 00:01:43,074 So in here, in this prepareAttempt method that we have going on, 30 00:01:43,074 --> 00:01:45,635 let's just make a new timeline. 31 00:01:45,635 --> 00:01:51,780 nTimeLine = new TimeLine. 32 00:01:51,780 --> 00:01:53,860 So we wanna set the cycle count. 33 00:01:53,860 --> 00:01:55,550 And the cycle count is essentially, 34 00:01:55,550 --> 00:01:58,990 in our flip book analogy, how many pages are available. 35 00:01:58,990 --> 00:02:04,020 So, we wanna have a page for every single second that we're gonna display, right? 36 00:02:04,020 --> 00:02:06,020 So let's set it to the total seconds that are required. 37 00:02:06,020 --> 00:02:10,900 So we'll say mTimeline.setCycleCount. 38 00:02:10,900 --> 00:02:14,170 And we're gonna set it to the total seconds that we're going to perform right? 39 00:02:14,170 --> 00:02:18,802 So that says run that, that many times, 40 00:02:18,802 --> 00:02:22,220 whatever 60 times 25 is. 41 00:02:22,220 --> 00:02:24,050 Run that times, cycle that many times through. 42 00:02:26,450 --> 00:02:30,380 Now next, what we need to set up is what happens on each page flip. 43 00:02:30,380 --> 00:02:33,370 Now these are known as keyframes, and you can have multiple keyframes. 44 00:02:33,370 --> 00:02:36,410 But ours is really only going to do one thing. 45 00:02:36,410 --> 00:02:41,400 So, keyframes is a property that returns a list on our timeline. 46 00:02:41,400 --> 00:02:42,850 So let's add one. 47 00:02:42,850 --> 00:02:45,000 So we'll say mTimeLine. 48 00:02:45,000 --> 00:02:46,870 We'll get the property, we'll say getKeyFrames. 49 00:02:48,390 --> 00:02:52,570 And we can just create a new one in line here. 50 00:02:52,570 --> 00:02:54,700 Could create this outside, but this is the standard way of doing it. 51 00:02:54,700 --> 00:02:55,740 I wanted to show you this. 52 00:02:55,740 --> 00:02:59,020 It looks a little over the top at first if you just see this written. 53 00:02:59,020 --> 00:03:02,040 So I just wanted to show this to you so you could grab it. 54 00:03:02,040 --> 00:03:08,180 So getKeyFrames, and we are going to do a new KeyFrame. 55 00:03:08,180 --> 00:03:09,780 Creating a brand new one here. 56 00:03:09,780 --> 00:03:12,360 And it takes two parameters, first it needs to know the duration. 57 00:03:12,360 --> 00:03:14,390 How does this run for, it's thinking. 58 00:03:14,390 --> 00:03:19,590 So you say Duration, and ours is going to run for exactly 1 second, right? 59 00:03:19,590 --> 00:03:22,590 You want to flip the page, let it go. 60 00:03:22,590 --> 00:03:25,510 Flip the page, wait a second, flip the page, right? 61 00:03:25,510 --> 00:03:30,950 So, 1 second, and then you can pass in a lambda. 62 00:03:30,950 --> 00:03:32,588 Okay, so we're going to do a lambda. 63 00:03:32,588 --> 00:03:33,839 And again, 64 00:03:33,839 --> 00:03:37,219 check the teacher's notes if you're not sure what the syntax of that is. 65 00:03:38,580 --> 00:03:42,250 And I'll import both of those things, okay. 66 00:03:42,250 --> 00:03:47,880 So in our lambda here, this is what is gonna run every one of these KeyFrames. 67 00:03:47,880 --> 00:03:52,110 So what we wanna do is we wanna take the current attempt, and 68 00:03:52,110 --> 00:03:55,620 we wanna make it take a remaining second down, right? 69 00:03:55,620 --> 00:03:57,600 We wanna tick the timer. 70 00:03:57,600 --> 00:04:00,390 So why don't we make a method called that? 71 00:04:00,390 --> 00:04:01,520 Let's call a method called tick. 72 00:04:03,250 --> 00:04:06,930 Of course, it doesn't know what that is so we will click it. 73 00:04:06,930 --> 00:04:08,370 And let's go create the method tick. 74 00:04:09,770 --> 00:04:12,910 All right, so, what does that do? 75 00:04:12,910 --> 00:04:15,630 Well, we want to decrement the RemainingSeconds. 76 00:04:15,630 --> 00:04:17,040 Okay, do you remember how that is? 77 00:04:17,040 --> 00:04:19,530 You go RemainingSeconds--. 78 00:04:19,530 --> 00:04:22,610 Okay, so that will take the existing time minus one. 79 00:04:24,730 --> 00:04:30,630 So, if we come back here, it should be working now. 80 00:04:30,630 --> 00:04:33,330 We'll see what that error is here in a second. 81 00:04:33,330 --> 00:04:37,380 And now what we wanna do is, each time we wanna set the timer text, 82 00:04:37,380 --> 00:04:39,510 remember that's that property that's automatically bound. 83 00:04:39,510 --> 00:04:42,380 We wanna set that to the RemainingSeconds. 84 00:04:48,090 --> 00:04:49,170 Let's see what this says. 85 00:04:51,040 --> 00:04:55,210 Oh, I forgot the word add, .add. 86 00:04:55,210 --> 00:04:58,350 We wanna call getKeyFrames and then we wanna add. 87 00:04:58,350 --> 00:05:01,180 So see it was so confusing even I typed it wrong. 88 00:05:01,180 --> 00:05:02,390 Let's read that again. 89 00:05:02,390 --> 00:05:05,220 We get all the KeyFrames that are currently existing cuz it's a list. 90 00:05:05,220 --> 00:05:08,970 And we add to it, and we create a brand new KeyFrame. 91 00:05:08,970 --> 00:05:12,480 And the brand new KeyFrame says, how long does it run for? 92 00:05:12,480 --> 00:05:13,270 And what does it do? 93 00:05:14,370 --> 00:05:17,670 And then because the cycle count says how many times it does it, 94 00:05:17,670 --> 00:05:19,040 basically we've just created our book. 95 00:05:20,240 --> 00:05:23,810 So now since we want to have multiple events be able to start and 96 00:05:23,810 --> 00:05:27,460 stop the timers, right, we have the play and the pause and the restart. 97 00:05:27,460 --> 00:05:30,060 Let's make a couple of methods right on the controller that explain 98 00:05:30,060 --> 00:05:31,190 what it's doing. 99 00:05:31,190 --> 00:05:34,300 How about, I dunno, playTimer. 100 00:05:34,300 --> 00:05:39,080 So we'll say public void playTimer. 101 00:05:41,110 --> 00:05:44,010 And it will know about the timeline, and so it will say mTimeLine. 102 00:05:44,010 --> 00:05:47,380 And there's a method on there called play, just as you'd imagine. 103 00:05:47,380 --> 00:05:50,130 And let's do one called pauseTimer, 104 00:05:50,130 --> 00:05:54,908 cuz multiple people might wanna call that as well. 105 00:05:54,908 --> 00:05:59,550 So say mTimeline.pause(). 106 00:05:59,550 --> 00:06:02,710 Cool, maybe we'll need more later in there, maybe we'll do other things. 107 00:06:02,710 --> 00:06:06,450 But for now, that will expose the method that kicks off the timeline. 108 00:06:06,450 --> 00:06:09,230 So one place I know for sure that wants to do that, and 109 00:06:09,230 --> 00:06:12,640 should be pretty clear, is the restart button, right? 110 00:06:12,640 --> 00:06:15,070 So let's go over to our FXML file. 111 00:06:15,070 --> 00:06:19,320 And in the Restart button, on this button here, let's go ahead and 112 00:06:19,320 --> 00:06:20,200 give that an action. 113 00:06:20,200 --> 00:06:26,135 So we'll say, onAction= handleRestart. 114 00:06:28,545 --> 00:06:32,220 And of course, that doesn't exist because we just made that up, so 115 00:06:32,220 --> 00:06:34,355 let's go ahead and say Create method. 116 00:06:36,885 --> 00:06:37,410 Awesome. 117 00:06:39,480 --> 00:06:42,010 All right, so when it restarts, what does it need to do? 118 00:06:42,010 --> 00:06:44,380 Well first we need to set up what attempt type it is. 119 00:06:44,380 --> 00:06:47,663 And no matter what, if you're doing a restart, it should go back, I believe, 120 00:06:47,663 --> 00:06:48,310 to focus time. 121 00:06:48,310 --> 00:06:52,070 So we should say, I'm ready to focus again. 122 00:06:52,070 --> 00:06:55,747 So if you click restart, 123 00:06:55,747 --> 00:07:00,126 we'll prepareAttempt, and 124 00:07:00,126 --> 00:07:06,090 we'll do AttemptKind.FOCUS, okay? 125 00:07:06,090 --> 00:07:08,980 And then, we'll just start automatically playing the timer, right? 126 00:07:08,980 --> 00:07:11,832 You don't need to set it and then have it sitting there waiting for us. 127 00:07:11,832 --> 00:07:13,870 We'll just automatically play the timer, it'll just start. 128 00:07:15,170 --> 00:07:16,310 Let's try that, let's see what happens. 129 00:07:19,720 --> 00:07:21,420 Okay, so let's click our Restart button. 130 00:07:23,560 --> 00:07:24,350 There it goes. 131 00:07:24,350 --> 00:07:25,300 Look at it clicking away. 132 00:07:26,510 --> 00:07:27,010 Awesome. 133 00:07:28,060 --> 00:07:30,300 So if I click it again, there it goes. 134 00:07:31,620 --> 00:07:32,940 Seems a little jumpy, that's strange. 135 00:07:34,870 --> 00:07:35,650 Oh, it's really jumpy. 136 00:07:36,840 --> 00:07:39,890 Oh, I wonder if it's clicking off multiple timelines. 137 00:07:39,890 --> 00:07:41,930 That's something we have to be careful of right. 138 00:07:41,930 --> 00:07:43,690 Cuz we told it to run this thing into the future, and 139 00:07:43,690 --> 00:07:45,480 it is running the thing in the future. 140 00:07:45,480 --> 00:07:50,880 Yikes, why don't we put a to-do in the code to fix that. 141 00:07:50,880 --> 00:07:55,590 Let's put that right right here we better say, 142 00:07:57,970 --> 00:08:01,388 And I'm gonna put my initials so 143 00:08:01,388 --> 00:08:05,944 anybody coming to look at this knows that, 144 00:08:05,944 --> 00:08:10,130 This is creating multiple timelines. 145 00:08:10,130 --> 00:08:14,510 We need to fix this! 146 00:08:14,510 --> 00:08:16,470 Yikes! 147 00:08:16,470 --> 00:08:20,230 We got our clock ticking, and our app is starting to work like we dreamed. 148 00:08:20,230 --> 00:08:23,850 One thing we need to think about is what happens when the animation is over. 149 00:08:23,850 --> 00:08:26,690 I think there was a user story about that wasn't there? 150 00:08:27,790 --> 00:08:30,490 Let's go start that story right after this quick exercise.