This course will be retired on June 1, 2025.
Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
Let's make our timer tick down and learn a bit about how custom animations in JavaFX work!
Learn more
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
[MUSIC]
0:00
Our time tracking app isn't very good
if we don't change the big block of
0:04
time, right?
0:08
So, there are a couple of ways
that we can tackle the problem
0:10
of making our clock start ticking.
0:13
I think the one that makes the most sense,
is to use timeline animation.
0:15
Have you ever seen one of those flip books
where there's a still picture on one page.
0:20
Maybe a stick figure going, and
then on the next page he's like, and
0:24
then almost the same one
on each different pages.
0:28
And then it goes kinda go like this.
0:31
And if you take the corner and flip the
pages, it makes it seem like it's moving.
0:33
This is animation in a nutshell, and
those are some sweet moves too, huh?
0:37
JavaFX provides different
powerful types of animation, and
0:42
I've linked to some fun examples
in the teacher's notes.
0:46
So what we are going to do is
make a pretty boring flip book.
0:49
On each page,
we're going to have the remaining time and
0:53
every second we'll flip the page.
0:56
So, we'll start with 25.
0:58
Wait a second.
1:00
Flip the page, and
it will say 24:59 seconds, etc.
1:01
JavaFX provides a pretty straightforward
way to accomplish this task.
1:06
So let's go learn all about the timeline.
1:11
All right, so the first thing that we
need to do is create a timeline object.
1:14
Let's add a private field to store it.
1:19
So we'll put it up here and
say, private TimeLine, and
1:21
we'll call it mTimeLine.
1:25
Now, every time that we prepare an attempt
to run, we'll just make a new timeline.
1:32
So let's do that.
1:37
So in here, in this prepareAttempt
method that we have going on,
1:38
let's just make a new timeline.
1:43
nTimeLine = new TimeLine.
1:45
So we wanna set the cycle count.
1:51
And the cycle count is essentially,
1:53
in our flip book analogy,
how many pages are available.
1:55
So, we wanna have a page for every single
second that we're gonna display, right?
1:58
So let's set it to the total
seconds that are required.
2:04
So we'll say mTimeline.setCycleCount.
2:06
And we're gonna set it to the total
seconds that we're going to perform right?
2:10
So that says run that, that many times,
2:14
whatever 60 times 25 is.
2:18
Run that times,
cycle that many times through.
2:22
Now next, what we need to set up
is what happens on each page flip.
2:26
Now these are known as keyframes,
and you can have multiple keyframes.
2:30
But ours is really only
going to do one thing.
2:33
So, keyframes is a property that
returns a list on our timeline.
2:36
So let's add one.
2:41
So we'll say mTimeLine.
2:42
We'll get the property,
we'll say getKeyFrames.
2:45
And we can just create
a new one in line here.
2:48
Could create this outside, but
this is the standard way of doing it.
2:52
I wanted to show you this.
2:54
It looks a little over the top at
first if you just see this written.
2:55
So I just wanted to show this to you so
you could grab it.
2:59
So getKeyFrames, and
we are going to do a new KeyFrame.
3:02
Creating a brand new one here.
3:08
And it takes two parameters,
first it needs to know the duration.
3:09
How does this run for, it's thinking.
3:12
So you say Duration, and ours is going
to run for exactly 1 second, right?
3:14
You want to flip the page, let it go.
3:19
Flip the page, wait a second,
flip the page, right?
3:22
So, 1 second, and
then you can pass in a lambda.
3:25
Okay, so we're going to do a lambda.
3:30
And again,
3:32
check the teacher's notes if you're
not sure what the syntax of that is.
3:33
And I'll import both of those things,
okay.
3:38
So in our lambda here, this is what is
gonna run every one of these KeyFrames.
3:42
So what we wanna do is we wanna
take the current attempt, and
3:47
we wanna make it take
a remaining second down, right?
3:52
We wanna tick the timer.
3:55
So why don't we make a method called that?
3:57
Let's call a method called tick.
4:00
Of course, it doesn't know what that is so
we will click it.
4:03
And let's go create the method tick.
4:06
All right, so, what does that do?
4:09
Well, we want to decrement
the RemainingSeconds.
4:12
Okay, do you remember how that is?
4:15
You go RemainingSeconds--.
4:17
Okay, so that will take
the existing time minus one.
4:19
So, if we come back here,
it should be working now.
4:24
We'll see what that error
is here in a second.
4:30
And now what we wanna do is,
each time we wanna set the timer text,
4:33
remember that's that property
that's automatically bound.
4:37
We wanna set that to the RemainingSeconds.
4:39
Let's see what this says.
4:48
Oh, I forgot the word add, .add.
4:51
We wanna call getKeyFrames and
then we wanna add.
4:55
So see it was so
confusing even I typed it wrong.
4:58
Let's read that again.
5:01
We get all the KeyFrames that
are currently existing cuz it's a list.
5:02
And we add to it, and
we create a brand new KeyFrame.
5:05
And the brand new KeyFrame says,
how long does it run for?
5:08
And what does it do?
5:12
And then because the cycle count
says how many times it does it,
5:14
basically we've just created our book.
5:17
So now since we want to have
multiple events be able to start and
5:20
stop the timers, right, we have
the play and the pause and the restart.
5:23
Let's make a couple of methods right
on the controller that explain
5:27
what it's doing.
5:30
How about, I dunno, playTimer.
5:31
So we'll say public void playTimer.
5:34
And it will know about the timeline,
and so it will say mTimeLine.
5:41
And there's a method on there called play,
just as you'd imagine.
5:44
And let's do one called pauseTimer,
5:47
cuz multiple people might
wanna call that as well.
5:50
So say mTimeline.pause().
5:54
Cool, maybe we'll need more later in
there, maybe we'll do other things.
5:59
But for now, that will expose
the method that kicks off the timeline.
6:02
So one place I know for
sure that wants to do that, and
6:06
should be pretty clear,
is the restart button, right?
6:09
So let's go over to our FXML file.
6:12
And in the Restart button,
on this button here, let's go ahead and
6:15
give that an action.
6:19
So we'll say, onAction= handleRestart.
6:20
And of course, that doesn't exist
because we just made that up, so
6:28
let's go ahead and say Create method.
6:32
Awesome.
6:36
All right, so when it restarts,
what does it need to do?
6:39
Well first we need to set
up what attempt type it is.
6:42
And no matter what, if you're doing
a restart, it should go back, I believe,
6:44
to focus time.
6:47
So we should say,
I'm ready to focus again.
6:48
So if you click restart,
6:52
we'll prepareAttempt, and
6:55
we'll do AttemptKind.FOCUS, okay?
7:00
And then, we'll just start
automatically playing the timer, right?
7:06
You don't need to set it and
then have it sitting there waiting for us.
7:08
We'll just automatically play the timer,
it'll just start.
7:11
Let's try that, let's see what happens.
7:15
Okay, so let's click our Restart button.
7:19
There it goes.
7:23
Look at it clicking away.
7:24
Awesome.
7:26
So if I click it again, there it goes.
7:28
Seems a little jumpy, that's strange.
7:31
Oh, it's really jumpy.
7:34
Oh, I wonder if it's clicking
off multiple timelines.
7:36
That's something we have
to be careful of right.
7:39
Cuz we told it to run this
thing into the future, and
7:41
it is running the thing in the future.
7:43
Yikes, why don't we put a to-do
in the code to fix that.
7:45
Let's put that right
right here we better say,
7:50
And I'm gonna put my initials so
7:57
anybody coming to look at this knows that,
8:01
This is creating multiple timelines.
8:05
We need to fix this!
8:10
Yikes!
8:14
We got our clock ticking, and our app
is starting to work like we dreamed.
8:16
One thing we need to think about is
what happens when the animation is over.
8:20
I think there was a user story
about that wasn't there?
8:23
Let's go start that story right
after this quick exercise.
8:27
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up