Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranรฎ)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Persian
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
1
In the last lesson,
2
we completed the user interface for our Pomodoro timer,
3
and we've managed to get all the components that we need onto our graphical user
4
interface. Now, the next step is to actually give it some functionality.
5
I want to be able to create some sort of countdown mechanism that just does
6
something really simple. For example,
7
if it was just able to count down from five, four, three, two,
8
one going down by one each time, that would be great.
9
That's what we're going to be working on in this lesson.
10
And we're going to go and see the countdown mechanism section to do that.
11
One of the ways that you might think about approaching this is to use our time
12
module
13
cause we've seen before that we can say time.sleep and we can tell it to
14
sleep for a second.
15
So then we could maybe set up a while loop and while something or other is true,
16
go ahead and sleep for one second. And then afterwards just,
17
you know,
18
subtract one from some sort of counter. So that we could start count at five
19
and then each time we subtract by one and then each time we just simply update
20
our label here,
21
which we created in the canvas to whatever value count might be.
22
Now, that sounds great in principle.
23
The only problem is that we're working within a graphical user interface
24
program.
25
The reason why that's relevant is because if we think about a command line
26
program, say for example,
27
if we were to get our console to do something, print
28
hello, well,
29
it's only going to do something when you actually give it an instruction and you
30
hit enter.
31
It doesn't really need to keep an eye out for what you might do in between.
32
But a graphical user interface is a little bit different.
33
It needs to keep watching the screen to see whether
34
if a user clicks on a button, for example.
35
So it's basically going to refresh and keep listening for events.
36
So every fraction of a second,
37
it's going to keep checking, did something happene, did
38
something happen, did something happen. And the moment when it does,
39
then it's got to react. It's got to react to that event.
40
In this case, we tend to call these types of GUI programs event-driven.
41
And the way that it's driven is through our main loop.
42
So when we set up our window and we start off the main loop,
43
it's basically looping through and every millisecond it's checking to see did
44
something happen, did something happen, did something happen?
45
So that means if we have another loop in our program,
46
it actually won't be able to reach the main loop. And in this case,
47
when you actually try to run it, nothing happens.
48
Our program doesn't even launch.
49
So we have to rethink this and we have to do it a little bit differently. In
50
order to create interactive and interesting programs,
51
you kind of need something to happen on screen, right?
52
Every so often. You need this timing mechanism. Luckily,
53
tkinter already thought of this.
54
And we can in fact use one of the builtin methods to every widget.
55
So if we tap into our window widget,
56
we can get hold of a method called after and after is quite simple.
57
It's a method that takes an amount of time that it should wait
58
and then after that amount of time,
59
it simply calls a particular function that you tell it to call passing in any
60
arguments that you want to give it. Here's how it works.
61
We call window.after, we first provide the amount of time to wait in
62
milliseconds. So if we want one second, then that's 1000 milliseconds.
63
Next we pass in a function to call.
64
So let's create a function up here. Let's just call it, say something,
65
and then we'll pass in the thing,
66
like this. And then all we do is we just print that thing.
67
So super simple function.
68
And then we give the name of this function as the function to call after 1000
69
milliseconds.
70
Now the final thing in this list of arguments,
71
if I just go ahead and cut that and show you again, when it gives me the prompt,
72
the last thing is actually a *args.
73
This, if you remember, allows us to put in an unlimited number
74
of positional arguments.
75
What that means is we can give as many arguments as we want
76
and those arguments, in this case, is simply going to be passed to the function
77
that we want to call. So in this case, it's going to be that thing.
78
So if I put hello here then I run my code,
79
you can see that after 1000 milliseconds, basically one second,
80
it calls this function,
81
say_something, and it passes this hello as the input
82
to that function. As I said,
83
you can have an infinite amount of positional arguments.
84
So let's put in some other arguments which we'll call a,
85
b, and c,
86
and then we'll print a, print b, and print c.
87
And now instead of passing in hello,
88
we're going to pass in lots of positional parameters. So we'll say 3, 5,
89
and 8. Now, when I hit run,
90
you will see it waits for one second
91
and then it passes all three of these parameters to say something
92
and it goes ahead and prints all of those out at once.
93
So this is how the after method works. But what we wanted to do though,
94
is we want it to repeat itself,
95
to essentially loop. One way of getting that behavior is to simply put this
96
method,
97
call somewhere inside a function and then call itself.
98
So here's what I mean. Let's create a function called a count_down,
99
and this is going to take a input in the form of the number to count down by.
100
And then inside this function, we call window.after.
101
And we say that after 1000 milliseconds,
102
call this function count_down and then pass in a count number.
103
If that count number started out as 5,
104
then we want to say count - 1.
105
Now all we have to do is to call this countdown method.
106
So let's call count_down and passing the starting count,
107
let's say 5 seconds. So now when I run the code,
108
it's going to call this method passing in 5 over here,
109
and then it's going to wait for one second,
110
and then it's going to call this function count_down passing in five minus one
111
so it becomes four. And then afterward it repeats again, becomes three,
112
two, one. So now if we catch that number
113
which we can print, then we'll be able to see it count down
114
when we run the code; five, four, three,
115
two, one. One every second,
116
and it basically keeps on going and it even continues to the negatives.
117
So if we don't want it to go to negative time,
118
then all we have to do is add an if statement.
119
If count is greater than zero, then go ahead and execute this line of code.
120
So now it'll go from five, four, three, two,
121
one, zero, and then it will stop.
122
This is the kind of behavior that we would need if we want to update our
123
countdown in our Pomodoro timer.
124
So how can we instead of printing
125
the count actually change this text on our canvas? We'll,
126
the way that we do that is by assigning this text a variable.
127
So I'm going to call it timer_text
128
and now that we've got timer_text being a set as the text that was created in
129
the canvas, then we can access it right here.
130
And the way that we'd change a piece of text or anything for that matter in a
131
canvas is slightly different from how we would do for a label.
132
If it was just the title label that we wanted to change, we would say title_
133
label.config, and then let's change the text to something new.
134
But to change a canvas element,
135
you actually have to tap into the particular canvas you want to change and
136
Then you call a method called itemconfig. And then in this method,
137
you pass in the particular item that you actually want to configure,
138
so in our case it's the timer_text,
139
and then you pass in the thing about it that you actually want to change in
140
terms of a kwarg, so this is a keyword argument.
141
We're going to change the text to the current count.
142
Now notice how this is not the string count,
143
because then it would just show that word,
144
but its actually the live countdown time. At this point in time
145
if I run the code,
146
I actually get a error and it tells us that the name canvas is not defined
147
and that's because I'm calling this method countdown before I actually created
148
the canvas.
149
So if I move that to below this line and I run it again,
150
then you'll see it actually work.
151
And you see it starts out from five and it counts down to zero.
152
Now how can we tie that behavior to the start button so that I can press the
153
start button and then and only then does it start counting down from five,
154
four, three, two, one? Well, let's go ahead and add
155
another function and I'm gonna add it in the timer mechanism section and I'm
156
going to call it start_timer.
157
Now this function is super simple.
158
All it's going to do is it's going to be responsible for calling that function
159
countdown and it's going to count down from five seconds.
160
So I'll move that inside the start_timer.
161
And now the start timer is going to be the function that needs to be triggered
162
when the start button gets pressed.
163
Do you remember how to tie a function to a button in
164
tkinter? Pause the video and see if you can solve this challenge so that you'll
165
be able to run the code, hit start and the timer to start counting down.
166
So the keyword argument is command and all we have to do is to tie it to the
167
start_timer function, but without the parentheses.
168
So now when I hit run and I click start,
169
it starts the timer setting that text from five, four, three,
170
two, one.
171
So the main loop is listening and when the user interacts with the start button
172
it actually calls the start_timer function which calls the count_down function
173
and get it to count down from five seconds.
174
Now we don't actually want to count down from five seconds.
175
We want to count down in minutes because we're probably not going to be working
176
for five seconds at a time.
177
We're going to be working for 25 minutes or having a minute break.
178
So how can I change this countdown to interpret this instead of as five seconds
179
to five minutes? Well, let's have a think about that.
180
If we wanted to count down, let's say one minute,
181
then that in terms of seconds would be 60 seconds.
182
All we have to do is to take the number of minutes that we want to count down
183
by and multiply it by 60. In this case,
184
if we wanted to count down it by five minutes instead of five seconds,
185
all we have to do is multiply by 60.
186
So then when we call this function count_down,
187
instead of getting five seconds to count down,
188
we get 300 seconds to count from.
189
But now if we run our code, you can see it's going to start from 300.
190
It's going to go down all the way down to zero. Now in terms of time,
191
that is five minutes, but this is not a very good way to visualize it.
192
Nobody thinks in terms of 288 seconds remaining, right?
193
So we have to format this count so that we can display it in the format of
194
00:00 like the usual kind of time, where for example,
195
you have one minute and 35 seconds remaining or something like that.
196
So how can we create something like this? If we have the count in terms of
197
seconds,
198
so let's say we have 300, and we wanted to know how many minutes where in that
199
then all we have to do is take 300 and then divide it by 60 and we would get
200
5, so that's 5 minutes. But what if the countdown has already been going
201
and instead we had 245 seconds remaining?
202
Well,
203
we can actually get hold of how many minutes and seconds that is equivalent to.
204
And the way we would do that is by taking that number, say 245,
205
dividing it by 60 seconds
206
and we would get a number 245 / 60 is 4.08,
207
3 recurring.
208
If we rounded that number down to get rid of all of the decimal places,
209
then that would be equal to 4 minutes.
210
And then if we want to get hold of how many seconds there are after we've gotten
211
hold of the four minutes,
212
then the way we do that is to use the modular because remember the modular
213
divides a number by another number, so 245 divided by 60,
214
and then it will give us the remainder.
215
How much is left after it's cleanly divided. And in this case,
216
this would actually be the number of seconds remaining after the four minutes
217
has been taken away. So let's write this code out.
218
The count minutes would be the count divided by 60,
219
but then we have to round it down so that we get rid of all of the remainder.
220
Now we don't want to round it so that if it was something like 3.6
221
it becomes 4.
222
We actually just want to get rid of everything after the decimal place. To do
223
that,
224
the easiest way is to import the math module and then use a function called math
225
.floor and this math.floor,
226
if I hover over it, is going to return the largest whole number that is less than
227
or equal to x.
228
If this was a 4.8, then the largest hole number less than 4.8 is 4.
229
So that's basically what this is going to do.
230
And this is going to give us the number of minutes. Now,
231
the next thing we want to do is to know, well,
232
how many seconds is left after we've taken away the minutes. To do this,
233
we're going to do counts
234
and then we're going to use the modulo to divide it by 60.
235
So the modulo is going to give us the remainder number of seconds after we've
236
cleanly divided it by 600. For example,
237
if we had 100 seconds and we divide that by 60, well,
238
that's going to be equal to one.
239
So we can minus 60 from 100 and we get 40 as the remainder.
240
That is what we will get after doing the modulo.
241
So that's basically the number of seconds that remains.
242
So now that we've got the minute and the second, we can actually change this
243
count to use an f-string and we can format it so that we add the count minute
244
first,
245
and then we add a colon and then we add our count in seconds.
246
Now look at what happens. We're going to try and count down five minutes.
247
So we get hold of the number of seconds, we pass it over to this function,
248
we work out what the count is equivalent to in minutes and seconds
249
and then afterwards we subtract one second each time.
250
So now when I run the code and I hit start,
251
notice how it starts from 5 minutes, goes down to 4 minutes,
252
50, 59,
253
and then it keeps ongoing like a real timer.
254
That's pretty cool.
255
The only thing left to figure out is how can we get it to not display 5:0?
256
How can we get it to display 5:00
257
like you would see on a clock? To find out how to do that
258
we have to learn about Python dynamic typing.
259
We have to understand how that works and that is what we're going to be talking
260
about in the next lesson. So I'll see you there.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.