In this video, we're going to talk about timers, and how to use them to affect the
state of our graphical programs. Okay. We're going to run the TimerHandler
on a regular interval so that we can change something in our program.
I think that you're going to find that this allows us to add an interesting
element to the excitement to our programs. So, let's get started.
In order to explain how to use timers to affect our graphical programs, I'm going
to, to use a simple screen saver program. Okay?
This is not a real screensaver by any means, but it's screensaver esque. Okay?
We've got text that moves around randomly on the screen every two seconds.
So, every two seconds a random location is selected and that text is redrawn.
So, the question is, how do we accomplish that?
Well, let's look at the code. Alright, we're going to follow the
structure for SimpleGUI programs that we've advocated.
First we are going to import our modules, SimpleGUI, and we are also going to import
random. And you can guess why we have to import
random cuz we need to pick a random location to place that text.
Then we have the global state of our program.sss After that, we have three
EventHandlers here that we're going to discuss in more detail.
We then create a frame that we can use. After we create that frame, we register
our EventHandlers and then finally we get the frame and the timer started.
Okay? The key to all this of course is the timer, and you can see here is where we
create the timer with a call to SimpleGUI create timer and we pass at two arguments,
interval and tick. Well, I don't know what those do. Well,
what do we do? We go to the docs. Alright, we go to the
docs, we find timer, we find create timer and we read that.
Timer takes two arguments, an interval and a timer handler.
And it says it creates a timer. Once started, it will repeatedly call the
given EventHandler at the specified interval, which is given in milliseconds.
So the first argument is how many milliseconds we want in between calls to
the second argument or the timer handler. Alright? And your timer handler should be
defined to take no arguments as follows, okay?
Alright, with that, let's go back to the code.
This is saying interval and tick. So what is interval?
To go up here. We can see that interval is a global
variable that we have that is set to 2000. So 2000 milliseconds,
That's two seconds. This is why our text is moving around at
this rate of once every two seconds. The second argument was tick.
And here's tick right here. This is our handler for the timer.
Alright, so what does this handler do? Okay, it's going to get called every two
seconds, by the system, as we discussed in previous lectures. Okay.
And it basically does two things. The first is, it picks a random position,
now that takes two lines here, where we pick x and y value, on the screen using
random.randrange and we pick between zero in width and zero in height.
Well, width and height are global variables, you can see above,
Here, That define the size of the canvas.
Okay. I'm also using width and height when I
create the frame, Down here.
Okay. So that I know that x and y will be
somewhere in the canvas. Now they might be right on the edge of the
canvas, but their gonna be in the canvas. Okay? Once I've picked these random
values, I'm going to change position. I'm going to set the 0th of position to x
and the first entry of position to y. You can see up here that position is a
global variable that is a list with two elements in it and those two elements are
xy position where we're going to draw the text..
Notice that the tick handler does not draw any text.
All that tick handler does, is pick a new position. Alright?
And, it's doing this once every two seconds.
There is no need to draw the text, that's not the job of the TickHandler. The job of
the Tickhandler is simply, to say, hey, two seconds have elapsed, I am going to
move the position that the text should be drawn at.
Okay? You'll notice, alright, when we registered out EventHandlers, we also
registered a draw handler, draw. So if we look at the draw handler down
here, this is our handler that actually does the drawing. Okay? And it only does
one thing, it takes our message, message is another global variable, it draws it at
a given position, position is our global variable that we modified in the tick
handler. Okay? And it draws it always in red in a font
size of 36. You can look at the docs to refresh your
memory on what draw text actually is doing.
Okay. Draw handler doesn't change the, position.
The draw handler only uses the position. Okay? So I have two things that I need.
I need the message I'm going to draw, and I need the location that I'm going to draw
it at. Both of those things are in global
variables. The draw handler does not update them, and
it does not care if anyone else updates them.
It just uses them. This is good program decomposition.
Okay, the tick handler doesn't worry about drawing the text and the draw handler
doesn't worry about where the text is, okay, or moving the text, right? And I'll
like to point out that the tick handlers simply runs once every two seconds.
The draw handler actually runs much more frequently.
It runs 60 times a second. Okay? So the draw handler runs a 120 times every
time the tick handler runs. Okay?
Alright, so let's run this again. Let's look at this. Okay?
So, what's actually happening here? The draw handler is constantly drawing
this text in the location that we've told it to, and then every two seconds the text
moves around, okay? How does it move around?
The tick handler sim, simply generates a new position, doesn't redraw it, just
generates a new position. The next time the draw handler runs after
that, it will draw the text in that new position. Okay?
And this is how the text bounces around. Okay? There is another element to my
screensaver here that I can change the message.
What do I want to change it to? Okay. I'm a little bit of a narcissist
here. You can see that I've changed the message.
Now what happened? Now the message is different.
I can keep changing it. Okay.
I am CodeSkulptor. Alright?
Now, there goes my message. Okay? I've changed it again.
What's happening here? Alright, if I look, I've also added an
input. Okay?
All right. And that input has a handler called update.
So whenever I hit return, it enters new text and calls this update handler.
Alright. We can see all the update handler is a sign message to be the text that was
in the text box. Okay? You can go look at the documentation
for ad input if you're a little bit confused here.
Okay? The message is a global variable, if you recall, and that global variable is
used in the draw handler to determine what text to draw.
So again, The update handler here does not redraw
the text, does not care about the position of the text,
All it does is, change the message, right, the global variable message which gets
used by the draw handler. So, this is a continuation of thinking
about decomposing your programs properly where the different event handlers don't
interfere with each other. They don't know or care what each other is
doing. They simply manipulate global variables
appropriately, and they do only what they need to do to make the program operate.
Okay? Now notice one thing here,
I had to say global message. Now, we've talked about this, right?
If I don't say global message, So, let's take that out.
Okay. I can change my message,
Warren is great. Hitting return here and nothing is
happening. Ha, this is very frustrating.
Yeah, I can't get that message out there for
you. Alright?
Why not? Okay,
Because it is not updating the global variable message now.
So the draw handler here is getting the old message.
Okay I need to use global. Alright down here in tic, notice I did
change position without having to type global.
Although I could, as we've discussed before, right?
This isn't going to change anything. I can type global position.
The program will still work. Right?
You can still see my text bouncing around. Right?
But it is not necessary. Why is it not necessary?
I'm not actually changing the entire thing of position.
I don't have position equals something. I'm changing elements of position and in
that case, the global declaration is optional.
Okay? So now you've seen how I can use a timer
to actually build a little simplistic screensaver and you've also seen some good
program design principles where I decompose the program.
I have an update handler that handles changing the message, I have a tick
handler that handles changing the position of the text and I have a draw handler that
simply draws whatever message we have currently at whatever position we have
currently. These things can run at completely
different rates, alright? The draw handler runs at 60 times a second.
The tick handle runs once every two seconds and the update handle runs only
whenever you type touch it, okay? But it still all works together nicely to
give us this interesting interactive application.
At this point in the class, we've talked about timers several times. However, in
this video we talked about how to use timers in graphical applications.
Think about the programming decomposition principles that I've talked about.
You just want to use timers to update global state on a regular basis.
The rest of your program should take care of everything else. All right? So, I'd
like you to look back at the example program, maybe play around with it a bit,
change the interval and see what happens. Maybe change the text color or other
things you can think of to change on a regular basis without putting to much
inside that timer handler. Hopefully you'll recognize now that having
timers like this will allow us to add an interesting element to our interactive