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
When a timeline completes, you will probably want something to happen. We do, so let's add an Event Handler to take care of the onFinished property.
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
So we know that when that clock hits zero,
we want some stuff to happen.
0:00
Let's go look at how to know
the attempt is completed, and
0:04
then figure out how to, and
what stuff we should do.
0:08
First, let's clean up that to do.
0:12
We definitely wanna stop the existing
timelines from running, so
0:13
that seems like we wanna do that.
0:17
Every time we create or
0:19
prepare a new attempt, we wanna wipe
out that existing timeline permanently.
0:21
So, let's take a look.
0:26
Let's think this through a little bit.
0:28
Let's come up here.
0:29
It seems like right about here, right?
0:31
So, there's gonna be a chance
that mTimeLine's not set.
0:34
So, we're gonna have to say,
like, it hasn't started yet.
0:38
So if it's not equal to null,
0:42
that's always a good thing
to do to check otherwise.
0:44
When you go to access a property, like,
we wanna see if it's running, right?
0:48
We wanna see if the thing's running.
0:52
So we're gonna say, get status.
0:53
And if I didn't check for that null,
what would happen when I called this,
0:55
we would get a null pointer exception.
0:58
And those are no fun.
1:00
So you'll always want to
check the state of things.
1:01
So then we're gonna say if the status, and
1:03
this status returns an enumeration
of animation.status.running.
1:07
That is a long looking line, isn't it.
1:17
So if it's not null and it is running,
we should just stop it.
1:22
So we'll say mTimeLine.stop[};, okay?
1:27
So that will stop it from
playing into the future.
1:30
Cool, we got that taken care of,
but you know what?
1:33
Those first couple of lines there, they
kind of look like they belong together in
1:35
some sort of method, don't they?
1:39
When stuff starts feeling like that,
1:41
like that doesn't really feel
like it's very succinct.
1:42
Like if I just look at this
like what is going on there?
1:44
Why don't we refactor this into a single
method and that way it will be cleaner as
1:47
to what's happening, as well as
the method could be called elsewhere.
1:50
So, when you get this feeling, a nice
thing to do is you come in here like this,
1:54
and you right click it and
choose Refactor, Refactor,
1:58
and we're gonna choose extract, and
let's extract that one more time.
2:02
Extract, and
we're gonna extract a method okay?
2:08
Private is fine, let's call that something
that makes sense for both of those.
2:16
We kinda want to reset things, right?
2:21
So let's call that reset doesn't
take any types, and click OK.
2:22
Okay, awesome.
2:28
So what it did is it took those and put
them into this new method down here, cool.
2:31
That's much cleaner now, I think.
2:34
We come in, we prepare the new attempt,
we reset the board.
2:36
So anything that we need to do that
resets the way that that screen looks,
2:38
we just put that function now.
2:41
And if we need to call that elsewhere,
we can also call it elsewhere.
2:43
Or if it makes sense at a higher level,
we could put that above that, make sense?
2:46
Great, now what we were doing?
2:51
Oh yeah.
2:53
Let's take a peek back
over here at the board.
2:54
So we still can't complete this one yet,
right?
2:56
Because as a user,
I should know what state I'm in.
2:58
If it's focus/break,
we have that going on.
3:01
We don't have paused yet, so
we're kinda blocked on that.
3:03
I guess we should start this one.
3:07
As a user in a Pomodoro attempt, I should
be notified when the attempt completes, so
3:08
that I'm aware of what my next step
should be, break or focus, okay.
3:12
That's cool, we can do that.
3:16
And while we're in here,
why don't we take a look at this one.
3:18
As a user, I should be able to
detail what my Pomodoro was about so
3:21
I can keep track of what's happened for
future planning.
3:24
So let's drag that over.
3:27
Okay, so we've got three of them.
3:29
We better get cranking on some of these.
3:30
We aren't actually going to save anything,
but let's mock it out.
3:33
So, let's flip back.
3:38
Okay, so, we want something to
happen when the timeline finishes.
3:41
You know,
when all the pages have gone through.
3:46
Well the good news is that an event
is fired when the timeline completes.
3:48
And it exposes a way for you to register
an event handler when it completes.
3:52
So let's do that.
3:55
And it's called setOnFinished.
4:01
And it expects an event handler which
means we can pass in a lambda like we have
4:04
been, which takes an event and
let's make it a multi-line.
4:09
I'm gonna do a couple things in here.
4:13
So, here is one of those weird cases where
a ternary might actually make sense.
4:15
Do you remember what ternaries are?
4:19
So, it's when you have the option
to go between two different things.
4:21
So, we want to prepare an attempt, and we
want to prepare the next attempt, right?
4:25
But how do we know what that is?
4:29
So, if we say that we
get the current attempt,
4:31
we get the kind of attempt that it is.
4:35
That's equal to focus,
well then the next one we know is break.
4:39
[INAUDIBLE] is right over,
my typing's bad there.
4:49
It's hard to see.
4:53
AttemptKind.BREAK, otherwise it's a FOCUS.
4:54
Does that make sense?
5:04
So it's saying, if the current Kind
is FOCUS, then switch it to break.
5:10
Otherwise, switch it to focus.
5:18
Make sense?
5:20
So that should take care of that
first ticket that we looked at.
5:21
Now the second one.
5:24
So we want to save the current attempt.
5:25
So we should probably do that before
we prepare the attempt right.
5:29
So let's come in here and
let's make a method.
5:32
I feel like we might be calling
this a couple more times.
5:35
So we're going to say save CurrentAttempt,
5:37
it's a method we that
haven't declared yet.
5:41
So, let's just go ahead and
have it build one for us, awesome.
5:43
You don't really have anything set
up on our actual model to save.
5:48
So, let's just make a mock method.
5:53
So let's do that.
5:56
We'll just have it print out
what we're going to save or
5:57
what it is that it's saving.
5:59
So let's so that.
So let's say mCurrentAttempt.save.
6:00
And of course, that method doesn't exist.
6:04
Let's go create it, okay.
6:07
So here let's print out Saving,
cuz we don't have a database set up and
6:10
it's kinda out of the scope
of where we're at here.
6:16
But it would save if this method existed.
6:19
And this is typically what it is called on
a model as you save it up to the database.
6:22
So we wanna print out the current object.
6:26
And the way that you do that is
with the keyword this, right?
6:29
That's referring to this instance,
make sense?
6:32
Oh yeah, you know what?
6:37
That reminds me we should generate
one of those toStrings methods and
6:38
this IDE will do it for us so
we're gonna generate to string, and
6:41
yeah all that stuff,
let's generate it all.
6:46
Cool, okay,
now one thing that we need to remember
6:50
is that we need to get the value
out of that message field.
6:54
Do you remember that we had
the message field at the bottom?
6:57
We could bind to that right.
7:00
So we could bind to it and
7:01
say every time that that field changes,
update the message.
7:02
But that seems like a little overkill.
7:06
Think if we just have this save current
attempt method and write right before we
7:07
save it, we go and get that value if
we say mCurrentAttempt.setMessage.
7:11
You know what,
why don't you go ahead and pause me?
7:18
I want you to pull the value
out of the message field.
7:22
Now, the message field isn't over here yet
in the controller.
7:25
How do we get that over here,
can you figure that out?
7:28
Pause me and come back.
7:30
Okay, did you get it?
7:33
Cool, so over at home.xml if we look down
here, this text area has an ID of message.
7:35
So let's flip back over here.
7:42
We will say @fxml that
is a private text area.
7:46
Be very careful not to get the java
awt It's a common, common error, so
7:53
this TextArea here is the one that
we want, and it is called message;.
7:57
Cool, so then if we come back
to where we were, sorry,
8:02
I am scrolling all over the place,
save message,
8:05
we wanna get message.getText cool, right?
8:10
Let's see how we did.
8:16
Two tickets,
let's see if we did two at once.
8:18
So, oh you know what though?
8:20
We don't have the play and
the pause button that's wound up.
8:22
I know, what if we change the temp,
8:25
temporarily we change the time that
was required on the first focus.
8:27
Then it would just switch over to break
and we'd make sure that we did it right.
8:31
So, let's go into our AttemptKind here.
8:34
And we'll go into our
definition of AttemptKind.
8:37
And let's change the Focus
time just temporarily.
8:40
Change that to three so we'll just
count down from three, all right.
8:44
Let's run it and see what happens.
8:48
So, we bound this button.
8:51
This restart button.
8:53
So it will go to three.
8:54
Two, one, boom.
8:54
Oh cool, and look.
8:58
Not only did it switch to break,
but it also saved and,
8:59
it doesn't have the message but
let's see if we can make it,
9:02
Have the message,
because we didn't have one there awesome.
9:09
It pulled the message and
the remaining seconds is zero.
9:13
So we can actually probably use that
save in a different way, right?
9:17
Whenever that restart was called,
we could do it.
9:21
Let's think about that.
9:25
Awesome job.
9:26
I hope you enjoyed the concept
of event listeners.
9:27
They are very prominent in most UI code
9:30
as it lets you hook into
different life cycles of objects.
9:33
So we pretty much got the visual stuff
in place to let the user know that
9:36
things are changing.
9:40
But if focus time is working correctly,
we should make sure that they really know.
9:41
We wanna snap them out of it.
9:46
Now JavaFX is super media friendly so
9:48
why don't play an appropriate
sound to get their attention?
9:51
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