 Hello, and welcome to our first Python antique intertutorial video. These first few videos are going to give you an overview of some of the very basic concepts and options that are available to us as we make our Python GUIs. I highly recommend watching these instructional videos first, so you have a strong foundation as we then dive into some of the cooler projects of the course. So I've opened up a new window here, and I've just called it basics0 underscore windows.py. That's going to be my naming convention. Feel free to name this file whatever it is that you'd like. Now, to run any tKinter or Python GUI app, it really boils down to the following four steps. First, import tKinter into your file. Second, create a main GUI window. Third, add some widgets to that window, and we'll learn about widgets like buttons, labels, and entries, et cetera, later on in this course. And then four, run your windows main loop, which is like a giant while loop that'll track any events triggered by the user on one of your widgets, like a user presses a button. So the first thing that we must do is import the tKinter library into our file. tKinter is the standard GUI library for Python, so it comes pre-installed with the base install of Python. So a simple import statement will suffice here. So I'll say import tKinter. Now we are going to end up needing to bring in more files as our apps get a little bit more complicated, and we'll talk about how we import those files later on. So let's see. We've imported tKinter, so now let's create our window. Common convention is to call the main window of your application the root window. So we're going to always call this first window the root window. To create this window, we'll call the tKinter library, and we'll create an instance of the tK widget. So tKinter.tk, and it's a capital T, lowercase k here. This creates a top-level widget that's going to be our root window of our application. Essentially think of it as like a giant container that we're going to put all of our other widgets into. And then we just worry about running this root widget, and when we run the root widget, all of the other widgets will also kind of be run and created. So in fact, I like to put a little comment here. Let's put a comment here. We'll say define a window. Now if I run this right now, nothing's going to happen, and let's talk about why, right? So if I run this, the code ran, I didn't get an error, but nothing popped open. And the reason why is because we haven't done steps 3 and 4 of the list that we made, right? We would have to maybe add some widgets to this window if we wanted to. We're going to not do that yet. We're going to get to that in our next video. But step 4 is really important. We have to run the main loop of the window. So in order to do that, I'm going to put a comment here. We'll say run root windows main loop. All right? I got to call root. So the name of my window is root, and I'm going to call main loop on this. And this is essentially what's going to create this root window, and it's going to continually run it. Think of it as like a giant while loop. And the only way we end the while loop is maybe by hitting the X of the window here. So now when I open this, look at this, we get a nice little window. My window looks specific to my operating system, Windows 10. So if you're running this on, I think, maybe Mac or Linux, your window might look a little bit different. But you can see we have a nice icon. We have a title. I got the minimize, maximize button, so I can do that here. Ooh, I completely closed that. There you go. Min and max, I can, I think, resize this window, and so we get some nice options. But it looks kind of bland, right? It kind of looks like, you know, just a plain window. What if we wanted to customize it? Well, don't worry, we most certainly can. So to customize this window, and so I'm going to make sure I do this above my call to the main loop of the root window. We got to, this should be our last line of all of our code here. Let's change the title first. So in order to do this, I'm going to call root dot, and I'll change the title property. So root dot title, and inside of here I'll pass a string. I'm going to say window basics. All right, so if I run this now, we should get a nice window with a different title. And so you can see window basics, perfect. Let's talk about how we might be able to change this icon from this, like little feather to something else that we want. To change the icon, we're going to look at the root windows icon bitmap property. Now inside here, you got to pass a string, which is a reference to the file name in question. So if I just open up my file explorer here, I'm going to just go to where I have this stored, code files, basics. You can see here's my file, basics0 underscore windows, and then here's my icon file thinking. So I have them in the same directory, which is exactly how I'm going to do it for the rest of this course. So to access that file, I just have to type in thinking, the name of the file, and then dot ICO. Now if you named your file something else, feel free to just type that file name in, and you can grab this ICO file from the resources of this video. So I'm always going to put my icons or images that I'm using as resources in our videos here. But let me show you where I get most of my icon files from. So if I open up the web browser here, and I go to icon archive, here's where I pull up all of my icons. So I think I called this thinking, right? So here it is, right? So thinking, really nice. And I can get it in different file formats, different sizes. And so when you're setting the icon, it has to be an ICO file. But if you're trying to just put images into your app, you can use PNGs or JPEGs, and we'll talk about how you go about doing that later on. One of the things I'll note here is that if you're going to use an icon or an image in maybe like a commercial application, make sure that you are allowed to do so. Other times, depending on what the license is, it may say you can use it, you can't use it, you can use it, but you have to give me credit somewhere. And so at certain points in this course, I might say, I got this icon from this website or from this user just to give them the credit that they need. All right, perfect. So if I run this, let's just check. We set the icon and there it is, that nice little thinking face right there. Perfect. Let's talk about how we might be able to resize the window, right? Maybe I don't like the size of that window. I want it to be a little bit different. I can do that by calling the geometry property. Now inside of here, this takes a string argument, which is the width of the window and then x and the height of the window. So you've got to set width x height. So I don't know, let's set this to be 250 by 700. So I want like a thin, tall window. And look at that, there we have it. So it looks a little bit, just like I thought, thin and tall. And you can see here, right, I can click on the edge and resize in the x direction and I can resize in the y direction. You may not want the user to be able to do that. And so we can prevent them from doing that by changing the resizable property. So root dot resizable. And inside of here, this takes two Boolean values. The first resizes in the x direction and then the next resizes in the y direction. So if I set like 0 comma 1, 0 says don't allow for resizing in the x direction. 1 says allow for resizing in the y direction. So let's just check this, right? If I look here, I'm trying to grab and it's not letting me resize in the x direction. And if I do it in the y direction, I should still be able to and I can. And if you look here, if I hit maximize, right, it only maximizes in the y direction now. A lot of times what I like to do is I like to set the width and height of the app using the geometry property and then I set the resizable property to 0 comma 0 so that they can't resize it. So now if you run this, you'll look, this maximized button is completely, it's grayed out so we can't use it. Perfect. Lastly, let's talk about a really important tool for us and that is using dot config. Using dot config on a widget, we can change specific options of the widget by just specifying what option it is that we want to change. So right here I can call root.config and inside of here I can pass an option or a property of the widget. For instance, I'm going to change the background color. So bg, which is for our background color. And I just specify what color I want to change it to. You can specify the color as a string or you can use hex values and later on we'll start using hex values as I think it works a little bit better. But for right now, there we have it, a nice blue window. And so you can see really quickly, we created a window that looked pretty basic and with a couple of changes we've made the window maybe more suitable to an application that we're trying to run. So I think this looks great. Now what if you wanted to maybe create more than one window? Well, your application really should only have one root window or one instance of the TK widget. That being said, your application can have any number of what are called top level windows. So let's talk about making a second window, second window. In order to make a second window, we're going to call TKinter's top level widget now. So I'm going to call my second window, I'll call it top and we'll say TKinter. And we want to access the top level widget, so top level. So as soon as I run this, I should now get two windows. And there we have it, right? Two independent windows. My first window, I've set all of those properties. The second window I did not set all of the properties. If I close the root window, however, both close, which is really nice, which is really nice here. Because remember it's the root window that's controlling the program. So we can set some of the properties of our second window here just like we did with the first. So let's set some of those properties right now. Let's set the title, so we'll say top.title and I'll change this to second window. And let's change the color, so I'll do top.config and we'll do bg equals and let's set it as a hex code, right? So let's do, I don't know, 1, 2, 3, 4, 5, 6. What's that going to look like? I'm really interested to see what color this is. Oh, it's a nice dark blue, right? And you can see, right, we've got, the title is different here, second window. Now if you notice, right, it just sort of opens up in a set location relative, right, it kind of is opening up right on top of our first window. I don't like that. So we can use the geometry property, top.geometry. I'm going to specify the height and width. Let's make it 200 by 200. And that's like, you know, just like we did up here with the root window. So then we can also specify where it is that the window is going to open up. So we can set a location, x, y, with 00 being the top left corner of the screen, okay? So this is 00 position. So increasing in x and then increasing in y going down. And so in order to do this, we just use a plus sign. And so I'm going to say in the x direction, let's shift it over 500. And then in the y direction, let's shift it down 50. And this is going to open it so it's not right on top of our first window. And so there you can see, right, over 500 and then down 50. Really nice, wonderful. So in this video, we made some windows for our upcoming applications. In the next few videos, we're going to learn about some of the different widgets that we can place into these windows and how we can use them in our apps to make them, you know, interactable. I'm looking forward to seeing you in those next videos. I hope you enjoyed this first one, and I will see you soon. Hello and welcome back. Now that we know how to open a GUI window, let's take a look at some of the various widgets we can place into our windows. Our first widget is going to be the label. A label widget is a widget that allows you to place text or images onto the screen. For right now, we're only going to talk about text. And in a later video, we'll work with images. To begin, we'll create our root window kind of like we've done before. So I have a new file here, and I've got this saved in the same directory that we were working out of. So let me just see here. If I come back, right here is our previous file. So here's our other file. So I'm going to put all of these files in the same directory with this image right now, kind of for these tutorials. So let's see. We'll put a comment here. We'll say labels and pack, so we'll talk about those. And the first thing we've got to do is we have to import tkinter. And so now let's define our window. So this is going to be a review of what we've done in the last video. So we'll call our window root, and we'll set it equal to tkinter.tk, and so that'll make a tk widget for us. Let's set the title. So we'll call the title label basics. Let's set the icon, so root.icon bitmap. And because I'm in that directory where the ICO file is, I'm just going to reference its name, thinking.ico. Now let's set the window size. So root.geometry. I'm going to set it equal to, we'll make a square window, so 400 by 400. I don't think I want this window to be resizable. So root.resizable, we'll give it two booleans of zero and zero. And lastly, let's set the background color. So I'll call root.config. And I'm going to set the background property equal to blue here. Awesome. And so if we want to make sure this works, right, we're going to run the root windows main loop, so root.main loop. So if I run this now, hopefully it'll look just like we had before, perfect. So we've got a nice window with our icon and title. We can't resize it, and the background is blue. Very good. So if you recall, right, step one, in our last video, we kind of introduced these steps of how do we make our application. Step one was import tkinter. Step two was make your root window. There was a step three, which was add your widgets, right? So we'll say create widgets. And then step four was run that main loop. So let's talk about our widgets here. Let's make our first widget our label. And remember, in this video, we're going to talk about labels, and we're going to just use text for all of our labels. So my first label I'll call name label one, and I'm going to set it equal to tkinter.label. So that will make a label widget for me. Now anytime we make a widget, we first have to pass the window or frame, and we'll talk more about what frames are later on, where the widget will be placed. Right now, when I just do this, tkinter has no idea where this label needs to go. So I'm going to pass in my root window. So now when I do this, this is going to place the widget in that root window or root frame. Next, I'm going to set the text that the label will display. So I'm going to say text is equal to hello, my name is Mike. Now I've created the label. If I run our window, all right, so if I run this, let's see, I've created the label. If I run this, though, the label doesn't appear. This is because even though I've created it, I haven't actually placed it onto the window. So it's kind of like a two-step process, right? Create the widget, and then place the widget onto the window. See, I have to tell Python where the label goes, essentially. Now there's a couple of different ways that we can do this in tkinter. The most basic and simple is to use the pack method. This method says, hey, you have a widget. I'm just going to pack it into the window in the next open and available spot. So let's pack the label now. So we've created the label, and so now we're going to pack the label. So let's see. In order to do this, I'm just going to call the label name label one dot pack. And I'm just going to do that for right now. Really basic, right? So if I run this now, it looks like, hey, cool, look at that. We've created the label. It appears. That's awesome. So let's make another one. So let's make another label. So I'm going to call this name label two, and I'm going to set it equal to tkinter dot label. We're going to make a label widget. I'm going to put it in the root window. I'm going to set the text equal to, hello, my name is John. And I'm going to set some other options here while I create this. I'm going to set the font. So I can set the font equal to, it's going to be a tuple, and it can take some values. I'm going to say the font family, so aerial, the size, I'll set it to 18, and then like the style option. So I'm going to say maybe bold here. So now I'm going to pack this onto the screen. So let's see, I'll say name label two dot pack. And so now when I pack this, it's going to pack it in the next available space. So it should pack it on the next line moving down. And it does. Really cool, right? So it packs it down. You can see the text is different and the font is also different for this label. Okay, let's keep going. Let's make name label three. Let's see what happens here. So name label three, we'll set it equal to tkinter.label. And we're going to put it in the root window. And this time let me set, I can define the text in the font just like I did here, or I can use config, right? So I could say name label three dot config. And then I could set text equal to, let's say hello, my name is Paul, all right? And I could set the font, name label three dot config. Font is equal to, we'll set it just, this time let's just use a font family of cambria. And we'll set the font size equal to 10. And I'm going to leave the font option blank, so I don't have to have that. And let's also change the background color this time. So I'm going to say name label three dot config bg is equal to, and I could specify, let's set it equal to red. So I could type in the word red, or I could use a hex value. So hex for red is ff 000. So now that I have all of this here, I can pack name label three into the root window. How does it know it needs to go into the root window? But when I've defined it up here, right, I've passed the root window here as an argument. So if I run this now, look at that, it works exactly the same using dot config. Sometimes it's nice to use the dot config method, but you know, here I don't maybe necessarily like it. It takes up a lot of lines, so I'm just going to set everything here. Hex is equal to hello, my name is Paul, font, I'll set to cambria, and a size 10, and then my background I'll set to the hex value ff 000. And so now I can kind of get rid of these lines here, and it should work exactly the same. Let's just check. Wonderful. Works really good. So if you notice here, when we pack this label, it sort of just kind of goes right up to the label that was before it, right? It's using all of the available space. Maybe we want to introduce some space or some padding around the widget. We can add padding in the y direction, the vertical padding, or in the x direction, horizontal padding. And we can do this when we call pack. So right here on line 20, where I am packing my third label, name label, I can add some padding. So let's add some vertical padding, let's see. So let's say pad, well let's add some horizontal, we can add some horizontal padding, pad x is equal to 10, and we'll add vertical padding, pad y is equal to 50. Now if I run this, we should see some space around our third widget. But if you look, hey, look at that added space, right? So here was our third widget, it's now shifted down, and in the x direction there's nothing else on the x direction to space it. So really that pad x10 really doesn't do anything there. But it's nice to introduce that that's an option that we can set when we call pack. All right, let's do another label, right? We're learning some really nice things about labels and packs here. So we're going to make another label. I'll call it name label four, and so we'll call this tKinter and we'll create a label widget. I'm going to fix it to the root window. And let's set the text equal to, I don't know, hello, my name is Sue. And we'll set the background color to let's set it to hex code 0, 0, 0, 0, 0. And the foreground, which will be FG, which is like the color of the font here. So foreground, let's set it to green. So remember, we can use hex values or we can use strings here for that. So if I run this, I got to pack it, of course, right? If I ran this now, we wouldn't see name label four because I didn't pack it to the screen, so dot pack. And if I run this, there it is, right? A black background, 0, 0, 0, 0, with green font, looks kind of cool. Let's mess around with this one with the pack here. So let's see. When we pack, we can add our padding, right? And so if I want to add some vertical padding, let's just say pad y is equal to like ten, right? So if I run this, this adds ten extra padding on the bottom. Remember, this widget here had 50 vertical padding on the top and bottom, and then we're adding another ten here. So really, it's like it's getting 60 padding in the vertical direction. If we only want to pad maybe to one side, like the bottom, we can specify it like this, right? So I can say pad y is equal to 0, 10. So this will say give 0 padding on the top and then 10 padding on the bottom. Perfect. So let's check if it's maybe noticeable. So you can see now that this spacing is equal here and here because we're only padding on the bottom. Now, if pad x and pad y essentially put space around the widget, we have something known as internal padding or iPad that puts padding inside of the widget. So let's see what this looks like now. Let's add some internal padding. So iPad x will set iPad x equal to 50 and will set iPad y equal to 10. So this is going to add internal padding on the widget. And so if you look now, there's more space in the horizontal direction because we set iPad x equal to 50. And there's some space here in the vertical direction now as well. So that's what internal padding does. Wonderful. You can really see that space. Lastly, let's talk about how we can anchor the widget. Anchoring takes essentially a compass direction like north, south, east, and west, and it pins the widget in that position on the screen. So let's anchor our widget to the west. So we'll say anchor equals west. So I'm just going to pass a string w. And what that's going to do, it's going to pin that label right there to the left side of the screen. Nice. So we really learned a lot with this widget right here. Let's do one last label. So name label five, we'll call it. So tkinter.label. I'm going to fix it to the root window. I'm going to set the text. We'll say, hello. My name is Pat. And let's set the background color to white. So I'll do that with hex codes, ff, ff, ff. And I'll set the foreground, the text equal to a hex color, I don't know, 1, 2, 3, 4, 5, 6. I think that was that really nice navy blue from the last video. And then, of course, let's pack this to the screen.pack. And well, let's just make sure that that works. We run this. All right, there it is. You can see we have right, there's a little bit of space here. Why is that little bit of space right here between these two widgets? Well, if you remember, name label four, we gave it some vertical padding, 0 comma 10, 0 at the top, and 10 at the bottom. So that's where that padding is right there. Now, let's say we want this label to fill in the whole space, OK? So right now it's just taking up this little bit. But if we want to make it larger, right, you can set the fill either in the x direction, the y direction, or both directions. So let's see what happens here when I type pack and we'll say fill equals, let's just put x. So let me close this, actually. And let me run this. So if you look, now the label has filled in the entire x direction here. Really nice. Let's change it to fill in the y direction. And let's see what happens. So we're going to set the fill equal to y. It doesn't really do it, does it? It kind of just takes up whatever space it needs. So let's add here another option, expand and set this equal to true. If we do this, it now expands in that vertical direction. So why really, when you fill y, it only fills into the height of the characters. So you can use the expand option to expand into the remaining space if you set it equal to true. Now, if you want to expand both x and y, I don't know, can you do x, y like this? Let's check. It looks like, so it says here, it must be x, y, or both. So can I type in a string both? I don't know if I can just do this. Let me see. It's not how I normally do it. So that does work, all right? So you can do it just like that. Or what you'll see a lot of times is we'll use both like this. Now, in order to do this, kind of maybe use this keyword, it's going to, I think it'll say it's not defined. See, it says name both is not defined. We can import this. And so a lot of times when you're importing extra things from TKinter, you'll see people do from TKinter import star. That will literally bring everything into your program. And I don't really like doing that. I only want to bring in what I'm going to use. So I'm going to say from TKinter import both. And so now if I do that, I can use this nice keyword here. And it should work without any issue. And there you see, all right? Perfect. Let's add some padding around this, right? I think if you add a little bit of padding, it might look a little bit nicer. So let's add some padding. We'll say pad x is equal to 10, and pad y is equal to 10. That should make it look a little bit nicer. And let's see. Oh, yeah. That looks a lot nicer. So there we have it, right? We made five label widgets. And we packed them into our root window. Labels are a great way to display text or images. Again, we'll learn how to use images shortly later on. The pack method is also really important because it provides a really quick and simple way to just place widgets onto the screen, right? We just say, hey, throw it in the first available spot, throw it in the next available spot. We can add some padding. We can kind of anchor them to different parts of the screen, et cetera. So I hope you learned a lot in this video. And I look forward to seeing you in our next video. Hello, and welcome back to these introductory videos on Python GUIs with TKinter. In this video, we're going to introduce a new widget, the button, and a new layout manager known as the grid system. So let's see. I'm going to save my file here. Let me just save it in the same directory. I've been working in, right? So code files. And let me just pull up all my, let me just do all files. There we go. So you can see, right? Here's our previous files that we've been making. And so I'm going to save it in the same directory. I'm going to call this basics2. And we'll call it buttons and grid, dot py. So there we go. So a button widget is exactly what it sounds like, something you can click and then click and then run a command or function. The grid system is a more robust layout manager in comparison to the pack system, which we looked at in our last video. If pack just literally packs widgets onto the screen into the next available spot, the grid system meticulously places them in very specific positions. So this gives us more control with the layout of our applications. So let's see how it all works. So first, I'm going to import TKinter. And let's define a TKWidget as our root window. And then we'll set some of the properties of that window. So this is what we've been doing in the past couple of videos. We'll say define window. And we'll call our window root. And we'll set it to the TKWidget. Let's set the title, so root.title. And we'll call this button basics. Let's set the icon, so root.icon bitmap. And we'll use our thinking icon. And again, because I'm in that same directory as this icon file, or ICO file, I can just reference it just like this. We'll set the window size of root.geometry. I don't know. We'll just do 500 by 500. And we'll make it so you can't resize it. Root.resizable, 0, 0. And I'll just keep the system background color. So I'm not going to change the background color. Let's call the root windows main loop. That's something that we know we have to do, so root.main loop in order to get our app to open. So if I run this now just really quick, all right, there it is. And I know I could have just copied and pasted this from all of our previous videos. But I think it's good for us to do it a few times. Kind of give us that muscle memory for what we're doing and why we're doing it. OK, so now let's make our first button widget. We'll call it name button. So let's see. We'll say create or define. Why don't we say define layout, right? Because this is going to be like the layout of the app. We're going to place our widgets onto the screen. So we're going to call our first button name button. And so we'll call tkinter.button. And that'll create a button widget for us. Now, just like our label widget, we first have to pass the window or frame where this widget will be placed. And in our case, it's the root window. So we'll type root here. We can also set the text property. So we'll say text equals, let's say, we'll just say name. OK, so I think that's good. Now let's put the button onto the screen. So previously, we used the pack system, right, name button dot pack. And that kind of just put it in the first available line, I guess we would say. It just kind of packed it in that first available space. There it is. And look, I can click the button, so that's cool. But we don't want to use the pack system for this. Let's use the grid system here. Now, the grid system breaks your window up into a collection of rows and columns, just like graph paper, right? It's a grid. You just need to specify which row and which column you would like to place your object. Now, these rows and columns are sort of built on the fly. So let me explain what I mean by that. And let's set in here for the grid, let's set row equal to 0, and we'll set column equal to 0. So we're going to specify the row and column. And so let's see how this changes our button. And so it looks like it puts the button in the top left corner of the screen, right? So row 0, right? We start with row 0 and column 0. So that's kind of exactly like you would expect. But let's change this now to row 2 column 2. Let's see what happens. So let's specify row 2, and let's specify column 2. And if I run this, we might think it might be down into the right, right? If this is row 0, row 1, row 2, and maybe column 2, we thought it might be down here, but it's not. It's in the same exact spot. The reason is because there are essentially no other widgets in row 0 or 1. There's no other widgets in column 0 or 1. So row 2 is the first active row. And column 2 is essentially the first active column. So the grid system places those rows in columns in the first available spot, which is the upper left-hand corner. So if that doesn't make sense to you, don't worry. We're going to expand on it shortly in this video. So let's see. I'll set this back to 0, 0 for right now. So we'll go back to row 0, column 0. Right now it doesn't make any difference, but it will momentarily for us. Let's make another button. This time, let's call it button time. So we'll say, or time button. We'll say time button is equal to tkinter.button. So it's a button widget. We're going to place it in the root window. And let's set the text. So we'll say text is equal to time. And this time, let's set the background color. So we'll say bg is equal to, and I'm going to use hex codes. We'll say 0, 0, f, f, f. All right. And let's now place this button. So we'll do time button dot grid. And we'll specify the row in column. So this time, we'll place the button in row 0, but now in column 1. So if we run this, actually, yeah, let's run this. So if I run this right now, here is row 0, right, the name button, and column 0. And this is row 0, column 1, our time button. And you can see our time button has that nice different color. Now that we've kind of put some widgets, other widgets, on the screen, let's change this back to row 2 and column 2. And let's see what happens. When we ran it with nothing else on the screen, we just shoved that name button in the top left corner. But now when we do it, look where the name button goes. The name button gets kind of moved around. And this is sort of interesting, right? So our time button is in row 0, but column 1 is the first column. So it kind of just plops it right here. There's nothing in column 0. And now our name button is in row 2. Well, row 2 is the next available column, or next available row. And column 2 is the next available column. So it does make a difference where we place these. So that's what I mean when I say we sort of build the rows and columns on the fly, all right? So we're going to change these back to 0, 0 here. Wonderful. Now let's make a button called place. We'll say place button. Place button is equal to tKinterd. And we'll create a button widget, buton, a button widget. We'll put it in the root window. We'll set the text equal to place. We'll set the background color equal to hex code. Again, we'll use the same color. I like to 0, 0, F, F, F, F. And this time, when I click it, I want it to change color. So I'm going to set the active, active background equal to a different color. Let's set it equal to red. So F, F, 0, 0, 0, 0. So by setting the active background option, that means when I click it, it won't just be that default like gray color. It will give me a different color that I want. So it'll give me that red color. So let's use the grid system to put this on the screen. So we'll call place button dot grid. And we'll put it in row 0. So we're saying that same row. And now we'll put it in column 2. So we'll put it in column 2. And this time, why don't we add some padding? So we'll set pad x equal to 10. We'll set pad y equal to 10. And let's give it some maybe internal padding. So we'll say ipad x is equal to 15. And if I run this now, we see our name button, our time button, and then we see that x padding of 10. And the y padding of 10 has essentially shifted the entire row down. By just giving the vertical padding on this button, it shifts the entire row down. ipad x, the internal padding of 15, gives me that internal padding. And now if I click time, it gives me that default gray. But for the place button, I've set the active background. It changes it to red when I click that button. Really, really nice here. Wonderful. Let's do another button, because we're learning a lot about how buttons work, how the grid system works. So this is good. We'll call this the day button. Day button is equal to tkinter dot button, buton. I find that funny. We'll place it in the root window. We're going to set the text equal to day. We'll do the background. I can use actual strings here, so I'll say black. And the foreground, I'll change the font color. By the foreground, I'll set it equal to white. And then we can also set the border width is another nice option that we can do. Border width, I'll set it equal to 5. And so you'll see a thicker border now around that button. Now, here, when we place this, I want to place the button on the screen. And I want it to be in a new row. And I want it to take up all three of the columns. So if we look here, if I do day button dot grid, if I want a new row, I can set row equal to 1. So this was my first row, row 0. And so now I'm going to move into the next available row. I could have done 1. I could do 2. I could do 3. It doesn't matter at this point. But as I expand and build my app, I want to make sure that I'm consistent. So I'm going to do row is equal to 1. Column is equal to 0. So let's just run this right now. All right, so there we have it, right? It's in its new row. It's spaced down. Why is it spaced down? Well, the place button, if you recall, we gave that a vertical padding of 10. So everything in this row gets a vertical padding of 10. And you can see the border is much thicker here. It's a nice, thick border now. So the question is, I want to have this take up all three columns, right? I don't want this button to just be here. I want it to take up this whole space. Well, we can span all three of those columns by setting the column span option. And so I don't want to span one column or two columns. I want to span all three columns here. So let's check this. If I run this now, it looks like the button is essentially centered in all three of those columns. So that's kind of good. We're sort of on our way here, but we want the button to take up that whole row, all of the space. Well, we're going to use a property of the grid system known as Sticky. So in here, I'm going to set the Sticky property equal to, and we can give it a compass direction. So Sticky is kind of like anchor that we use with the PAC system. You give it a compass direction, and it will sort of pin the widget. So if I just type in W, and I think it's capital letters here, if I type in capital W, it should pin it to the west. And it does. And if I type in E, it should pin it to the east. And it's going to pin it all the way to the end of the, yeah, because remember, we're spanning all three columns here. If I wanted to go across all of them, I'll do from west to east, just like this. This will expand the widget in the horizontal direction for us. Perfect. So now it takes up that entire row. That looks really, really nice. So one last thing I want to do here is I want to make a collection of test buttons. So let's call this test 1. We'll just call it test 1, tkinter.button. And we'll say we're going to put this in the root window, and the text is just equal to the word test. And I'm going to copy this and paste this, I think, five more times. So let's see. 1, 2, 3, 4, 5. And I'm just going to rename these buttons. Test 1, test 2, test 3, test 4, test 5, and test 6. And so now what I'm going to do is let's put these test buttons on the screen. We're going to put them in rows 2 and rows 3. And so let's see. Test 1.grid. We'll put it in row 2, column 0. I'm going to give it some horizontal padding of 5 and some vertical padding of 5. And so I'm going to just copy this quickly. And 1, 2, 3, 4, 5. And we're just going to change these numbers. 2, 3, 4, 5, and 6. All right, so my first button is going to be in row 2, column 0. My second button is going to be in row 2, column 1. And my third button is going to be in row 2, column 2. I'm sorry, so 0, 1, and 2. And then we're going to change these rows to row 3. We're going to put them in the next row. And button 4 will be in column 0. Button 5 will be in column 1. And button 6 will be in column 2, just like that. Awesome. So let's run this. And let's see what this looks like. So I should have two nice rows of buttons. And so they are there, right? So we get two rows. But you can see the odd spacing here. And I don't really like this. In fact, what I really want are two rows of evenly spaced out buttons. Well, I'm not really going to get it here. And the reason why is the size of each column, right? Column 0, column 1, and column 2, the size of those columns is defined by the largest item in the column. So my third column's width is defined by the place buttons width. So when I put a new button in the column, it gets centered into that column by default. So you can see, right, we're getting centered right here. And it throws off all of our spacing. A temporary fix may be to use sticky and pin the button to the west. So let's try this. So let's go to test 3 right here, right? And we'll say sticky equals west. And I can do this down here as well. Sticky equals to the west. And so that gives me a little bit better spacing. You can still tell, though, that there is a little bit of odd gaps here. So this is kind of like a temporary fix. It looks OK, but I think there's a better way to handle this. And I'm going to show you how we handle trying to redefine our columns and our rows in upcoming videos. I think this is a good place to stop. In regards to placing things on the screen here with Python and Teacenter, PAC is a good quick method to get items on the screen when the layout's not complicated. If you have a more complicated layout, the grid system is a much more robust tool for you to use. It gives you a lot more control. We're going to work with both of these layout managers, PAC and Grid, throughout the scope of this course. I hope to see you in our next video. Hello, and welcome back. In our last video, we saw a complication to the grid system. The column size is determined by the largest widget you place in the column. This can then make for some layout difficulties, like we saw with our row of test buttons. To make life easier, when you know you have certain sections of your layout that are going to go together, you should use a frame. The frame widget groups and organizes other widgets together. It works like a container, which is responsible for arranging the positions of other widgets. You put other widgets, like buttons and labels, into a frame, and then put the frame onto the window. So let's start by making our window and setting some properties. So import tkinter, and it will say define window. And again, we'll make a root window by calling a tk object, or tk widget, I should say. We'll set the title, root.title, frame, basics. We'll set the root.icon bitmap, and I'll use my thinking icon, so thinking.ico. I'll set the geometry, root.geometry. We'll make this 500 by 500. And I'm not going to care if you can resize this if you want to, so I'll leave the resizable off. And so now let's run the root windows main loop. So run root windows main loop by calling root.mainLoop. All right, and so that should run our window here. Wonderful, looks good. Perfect. Okay, so we know that frames are going to help us better control the layout of our application. So let's see a great example of why. I'm going to make a label called nameLabel, and why don't I put a little comment here. We'll say example of why to use frames. So I'm going to say nameLabel is equal to a label, so tkinter.label, it's a label widget. We'll put it in the root window, and we'll say text is equal to enter your name. And then we're going to pack this onto the screen. So nameLabel.pack, we'll use the pack system. So we packed this right onto the root window. Now I'm going to make a button. So we'll make a button called nameButton. NameButton is equal to tkinter.button. And we'll put it in the root window, and we'll say text is equal to submit your name. So we'll try to enter your name and submit your name. And now I'm going to use the grid system to put this in a specific spot. So I'm going to say nameButton.grid, and I'm going to put it in row zero column one. And so if I run this right now, let's see what happens. We get an error, and it says, we cannot use geometry manager grid inside our essentially root window, which already has slaves being managed by pack. So you see, you can't have more than one layout manager running at once for a specific widget. This is kind of like a big bummer, right? Our tkwidget, we started using the pack manager and your layout manager, and then we tried using the grid layout manager too with it. And it gave us an error. So you're not going to pack a few widgets onto the screen and then maybe make a row of three widgets using grid. It's not going to work. Of course, you could do this if you used frames. When you use frames, you can use whatever layout manager you want within the frame as long as you are consistent in your choice within that frame. So if you make a frame and you can use pack within that frame, then you make a new frame, you can use grid, et cetera. So let's maybe comment this out. It's good to keep that there, example Y. So now let's put a little comment here. Let's make some frames. So define frames. Let's define these frames. We're going to make three frames here. Now you can make a frame widget or a label frame widget. They're essentially kind of the same thing. The difference is that a label frame widget gives the frame a nice border and you can display a text label or image label right within the frame border. So let's see. We're going to create our three frames and we're going to place them in the root window and then we'll give them specific background colors, I guess. This first frame we'll call pack frame and we'll call the frame widget. So tkinter frame. We have to put the frame or assign the frame to a window. So we're going to assign it to the root window and then we'll set the background property. We'll just set this equal to red so we can really see it. And then we're going to call gridframe1. We're going to make a frame called gridframe1. So tkinter.frame. And again, I'm going to assign it to the root window and I'm going to set the background property to blue. And then I'll make one less frame. I'll call it gridframe2. And this time I'm going to make it a label frame. So a label frame, label frame. And again, we have to assign it to a window. So we'll assign it to the root window. The label frame, I can put a label right within the border of the frame so I can set the text property here. And I'll just say grid system rules. And maybe I'll set the border width equal to 5 here. So there are three frames that we defined. So now I can pack the frames onto our root. So I'll say pack frames onto root, the root window. And so in order to do this, if I want to pack them, we're just going to pack them right on top of each other. So one on the top, then the next, and then the next. So we'll say packframe.pack. We'll say gridframe1.pack. And we'll say, oops, there we go, gridframe2.pack. And there's nothing wrong with this, right? Because for the root widget, my TK widget, which is way up here, I'm only using one layout manager. And that's the pack system. So if I run this, let's just take a look. If I run this, we don't really see anything, right? We see nothing. Well, we sort of see something, I guess. We see some little squares, like colored squares, right here and here. This is because there's nothing within these frames, right? So there's no reason to expand the frames. There's nothing inside of them. So those are the frame sizes are extremely small. But we know how we can expand a widget. So I'm going to use the both keywords. I'm going to say from TKinter import both. I'm going to bring that keyword in. And then down here, when I pack these frames onto the screen, I'm going to say fill is equal to both. And we'll set expand equal to true. True, there we go. And I'm just going to copy and paste this. And so we saw how to do this in a previous video with our widgets. And while we're at it, so if we run this, let's just check. This should now bring our frames out. All right, so we've got a nice red frame, a nice blue frame. And then you can see the label frame gives us a nice border. And we can put a label right in here. So it says grid system rules. While we're at it, let's just fill in the second frame in the x direction. Instead of both, let's just do x. Why not? So we'll say x. And let's add some padding on our third frame. So I'm going to say pad x equals 10, pad y is equal to 10. Give it a little bit more space. So I'm just trying to refresh what's going on with some of the other commands here. So now if you look at our second frame, the fill is just in the x direction. When we add some widgets, this will begin to expand in the y direction. And now you can see some nice padding here on our third frame. I think that looks really good. So now we have three frames where we can set the layout independently of other frames. So in our pack frame, this first one right here, let's use the pack system to throw some labels onto the screen, just one on top of the next. So let's see. Down here, I'm going to put a comment. I'll call this pack frame. And we'll say tkinter label. And I'm going to put it onto the pack frame. The text is equal to, we'll just say text. And now I'm going to call right on this dot pack. So this is another way that you can do it. Before I was creating the widget and then packing it onto the screen on two separate lines, you can do it all on one line just like this. But when you do this, be careful because you don't have a reference to this object now. So if I run this, it should work. See, and there's text. But I have no reference to this little label right there. And so while it works, it sometimes might not be the most efficient way to do it. But for right now, we'll show you that that's one of the ways you can do this. So we'll make another label tkinter.label. Oh, it's actually, let's just copy and paste this three times. Let's do that. So we'll just pack these right onto the screen. So copy, paste, and paste. And so remember, the pack system, just one on top of the other in the next available spot. Perfect. Let's go to a different frame now. So let's use grid frame one, a new frame so we can use a new layout manager. Let's use the grid system to kind of make a staircase of the word text. So down here, we'll say grid one layout. And I'm going to say tkinter.label. I'm going to make a label. I'm going to put it in grid frame one. And the text is going to just equal text. And like before, I don't really need to keep a reference to any of these widgets, at least for this simple purpose. So I'm just going to call dot grid on it. And I'm going to put it in row zero column zero. All right. And so now I'm going to copy that. And I'm going to paste this a few times. All right. And so we'll say row zero here. We'll change this to one and one. And then we'll change this to two and two. So if we look, right, there we go. If I run this, no errors at all. And so that's kind of nice. And you can see how this frame has expanded in the vertical direction and the y direction to fit these widgets. So that was nice there. If we look, we created our three frames and we put them on the root window using pack. Then we took our labels and we placed them onto the pack frame. So those are those three. And then we took our other labels and we put them onto the grid frame. Those are those three. And we use the different layout managers. So that's pretty nice. Let's keep going. Let's try to put a really large label in row four column zero. So I'm going to put a really large label right here in row four column zero. I just want it to span all the way across here. So let's say tkinter.label and we'll say grid frame one. And then we'll say text is equal to all of that really, really big stuff. And then we'll do dot grid. And we'll put it in row three column zero. Let's see how this works. Oh, I forgot an equal sign. Let's see, row equals three, column equals zero. Let's run that again. OK, when I do that, oh, it looks terrible. You can see, look at our nice little staircase that we had built. It completely throws the layout off. Because remember, this first column, the width of that column, is defined by the largest widget, which is inside of it, which is this kind of massive label right here. Really not what we want. So let's move it. Let's move this label to our other frame. If we move this label to our frame, these two layout managers should act independent of each other. And so our staircase should be rebuilt again. So I'm just going to comment this line out. And let's go to grid frame two here. So we'll say grid two layout. And let's just, I'm just going to copy this actually, let's put this widget back in. And so now here, instead of grid frame one, I'm going to attach it to grid frame two, the other frame. And now my row, I'm just going to set it to row zero, column zero. And if I run this, all right, it looks perfect, right? There's our label and our staircase is still intact. Since the layouts are independent, we're able to place this new label in the second grid, that's grid two frame. And it won't affect what's in that first grid frame. Perfect. See, frames in conjunction with pack and grid systems can help you when you're trying to make some rather complicated layouts. For simpler layouts, we may just use the single root window. But when we start getting more complex layouts, you can bet we'll rely on the use of frames. A lot of times I like to create maybe input and output frames for the sections of my app that will get user input and then give output based on that input. So you'll see us doing that a lot in some of our upcoming videos. OK, I think that's it for this video. I hope to see you in our next video. Hello and welcome back. We're well on our way to having a solid foundation in some of the basic principles and ideas of Python GUIs and TKinter. And that's going to help us build some pretty awesome apps as we move forward. We've learned about some of the basic widgets TKinter has to offer, such as TK windows, labels, and buttons. We've also seen some basics of how we can manage our application layout with the pack and grid systems and frames. In this video, I'd like to show you how you can program some of the functionality of your application and make it more interactive using functions. Also, we'll learn our first way to get user input via the entry widget. So let's begin by making our TK window and setting some of its properties. So let's see. We've got to import TKinter, all right. And we're going to put a comment here, define window. And so we're going to make our root window by calling TKinter.TK. We'll make a TK widget. And let's set the title, root.title to entry basics. We'll set the root.icon bitmap. Again, I'm in that same directory we've been working out of, so I can just reference my icon as thinking.ico, because it's right there in that directory. We'll set the window size, root.geometry as a 500 by 500 window. And I'll set it so we can't resize it. Root.resizable by giving two zeros here for the x and y. And let's run the root windows main loop by calling root.main loop. All right, let's just test it. Always good to make sure that that's working. Again, we're going to go through this just a few times here in these introductory videos just to make sure we get a good handle for the steps that go into making a basic application here. Awesome. I think this looks perfect. So now let's make a couple of frames. We're going to be getting user input via an entry box, an entry widget, and then we're going to do some work with it and then spit it back out. And so we're going to have an input frame and an output frame here. We're going to place both of these frames in our root window and let's give them a background color. So we'll put a comment here, define frames. I'm going to call my first frame input frame, and I'm going to set it equal to a tkinter frame widget. I'm going to put it in the root window, and I'm going to set the background color equal to hex value 0, 0, 0, 0, ff, which is going to be a really nice blue. Let's see, the output frame, output frame. I'm going to set this equal to tkinter.frame, a frame widget. We'll put it in the root window, and I'm going to set the background color to a nice red, hex value ff 0, 0, 0. Now, our root window, let's use the pack manager to put things onto the screen in the root window. I'm just going to call input frame dot pack, and I'm going to give it some padding, pad x equals 10, pad y equals 10. And then I'll call output frame dot pack, pad x equals 10. And for right now, let's do pad y equals 10. We might change that in a second. So let's run this. So if I run it, no surprise, you can see a little square and a little square. And that's because we didn't expand and fill these frames. You saw in the last video or a couple of videos ago, we had expand equals both, fill equals true, or fill equals both, expand equals true. That made the frames blow up. Right now, there's nothing in them, and we haven't done that. So those frames are extremely small. But we can set a new property here in the frames when we define them, the width and the height, to give them a specific size. So let's set the width of my input frame equal to 500. So it's going to take up the whole window width. And then let's set the height equal to 100. So it should just be a small top portion of that. And down here in the output frame, let's set the width equal to 500. So it'll take up the entire window frame. And let's set the height equal to 400. So we can sort of kind of set the size here of our frames. And so now this should expand them. Hey, I think that looks pretty good. I'm noticing something that I don't like is that you have this uniform spacing all around the frames. And then it's kind of larger here in between the two. And that's because the input frame has a vertical padding of 10 on the top and the bottom. And the output frame has a vertical padding of 10 on the top and the bottom. So that means right here, you get 10 from the bottom and 10 from the top. That makes 20. So we can change this by just saying, OK, output frame, 0 on the top, 10 on the bottom. We'll pass that as a tuple. And if I run this now, it should give us some nice uniform padding, which I'm going to like a lot. Yeah, I like it a lot. And you should like it too. It looks really good. It looks really, really nice here. Perfect. So I think I have a couple of these apps open. Let me close them. There we go. OK, so now let's add some things to our frames. Let's add to our input frame. So for our input frame, we want the user to be able to type something into our application. And so this is where the entry widget comes in handy. So let's create an entry widget. And so right here, I'm going to maybe put a little comment. I'm going to say, add inputs. And so we'll call this widget text entry. And we're going to set it equal to the entry widget. And now I want to put this widget on the input frame. So I'm going to put it on the input frame. And right now, I'll just leave it like that. And the input frame will use the grid system. We'll use the grid system here. I'm going to say text entry dot grid to put it on the screen. We'll say row equals 0, column equals 0. So that'll put it in the upper left hand corner of the frame. And let's give it some horizontal padding and some vertical padding. And so let's just run this right now. OK, perfect. A few things you notice here. The frame, this is a specific size. We can change the width of the entry. So let's do that now. Let's come up here back to our definition of the text entry. And we'll say width. We'll set the width property equal to, I don't know, 40. So that should make it a little bit larger for me, which is what I want. Who knows how much? There, look at that. That's nice. Who knows how much stuff we're going to be entering in here? But one of the things you might notice is that the frame has kind of changed its size, right? So the frame has taken the shape of the widget that it holds, since this widget is the specific size. The frame doesn't need to be any larger than that. I don't want this to happen right now. And so there is a property of the frame that we can then change. And so I'm going to come down here right after I put those inputs. And I'm going to call input frame. And now there's two ways you could do this. You can do it for the grid system or for the PAC system. Since the input frame is being managed by the grid system, I'm going to call grid underscore propagate. So grid propagate. And I set a Boolean value in here. I give it a Boolean value. I'm going to pass a 0 here. This means that the frame will no longer resize to the size of the widgets that it contains. So it should always just stay the same size now. So let's run this in check. Hey, perfect. Look at that. And my input bar is right here in the upper left-hand corner with some nice horizontal and vertical padding. So that grid propagate is working nicely. Awesome. So now let's make a button that will hopefully do something with whatever text that the user puts in. Let's call it the print button. So we'll come down here and underneath this comment for the inputs. We'll say print button equals a tkinter.button. And we're going to put it in the input frame. That's where we're putting it. The text will say print. Why not, right? And we're just going to leave it blank just like that. And so let's put this on the screen here. So we'll do print button dot. We have to use the grid system, right? Because the input frame is being managed by the grid system. So everything that goes on it has to be the grid system. And we'll put it in row 0. But this time we'll move it to column 1. And we'll give it some pad x of 5, a pad y of 5. And I want to add some internal padding, right? If I run this right now, I think the button's going to look kind of small. Let's just see. Yeah, it looks kind of weird in comparison to what else is in here. So I'm going to add some internal padding. I'm going to say ipad x is equal to, I don't know, let's say, if I do 40, is that? Well, let's do 30. Sometimes you just got to feel it out. You got to see what it looks like. Do I need a little bit more? Yeah, that's pretty good. I like that. OK, so that's good. Perfect. So now it looks like we have this button. But right now when we press the button, right, if I look, let me just run this again. If I press the button, nothing happens. So I can type something in here. But when I press the button, absolutely nothing happens. This is because we somehow now have to link the button press to a specific command or action in our code. And so we can do this by setting the command property of the button. So let's go back to our button definition. So here's our print button. Here's where we defined it. Let's set a new property, the command property. And I'm going to set this equal to a function that we are now going to write. So I'm going to set this equal to a function that I'm going to call makeLabel. So it's going to makeLabel. So I've set the command property equal to some function that I'm going to write called makeLabel. So I should probably write this function. Now you want to make sure you define your function above wherever your function calls. I always like to define my functions right after I define my window. So I'm going to say def makeLabel. All right. And we'll give it just a simple doc string, right? Why not? Print a label to the app. There we go. So in here now, anytime I press this button, it's going to run this command. So anytime I press the print button, it's now linked to the makeLabel function. And the makeLabel function will run. So I mean, just really simply, right? If I just type print hello world, oops. Hello world. And I run this now. Just in my terminal here, it should print it anytime I type it. So if I print hello world, hello world, hello world. This action is now linked. And the action is being monitored because the root main loop window or main loop is constantly running, right? This while loop is constantly running. So it's registering that action. Now what we really want, we don't want to just print to a terminal. We want to make something happen in our application. So let's talk about how we might be able to do that. All right. So in here, we have to define this function. But once we do, it's going to work all the time. So in our makeLabel function, we want to output our entered text to the screen. So let's make a label and place it in the output. So I'm going to make a label, all right? Because that's what we use to create text to the screen. So I'm going to call this label text. And why don't I call it? Yeah, I'll just call it text. Equals a tkinter.label widget. I want to place it on the output frame. And the text, I want to grab whatever text is from our entry box. So to do this, we can use the .get method. So I'm going to say text is equal to my widget that is the text entry box. It's called text entry. So I'm going to reference that name, text entry. And then I'm going to get whatever text is in that box. A lot of times, I forget to put the .get. And it tells me that there's an error. And I can't figure out why. And then I have to remember, oh, I have to call .get to go get that text. So now that we have that text, let's pack this label to the screen. So the output frame, we'll just use pack to control its layout. So text.pack, we'll put that there. And then the last thing that I really want to do, let me show you. I'll run this right now. Let's see. So let's just make sure that this is working. So I'll say hello world. And so if I click print, it now prints it right there. Awesome. A couple of things we'll notice is that the whole label just disappeared. It took the size of this. I don't like that. We'll get to that later. But one of the things I'd like it to do is kind of clear this entry box after I click print. I don't want to have to go back and manually delete it like that. So let's talk about how we could do that. So to clear that entry box, I'm going to call the .delete method, which is going to take two arguments. So I'm going to call text entry, which is the name of the entry box that I have, .delete. And now it takes two arguments. The first index that you're going to go to and the last index that you're going to go to. Well, we want to start at the beginning of the field. So we're going to use 0 as our starting index. But the last index is going to change based on how many characters the user has typed. So let's bring in the end keyword. And what this is going to do is it's always going to go to the end of the user's string that they put into the entry box. We just have to make sure that we now import this. So I'm going to say, from tkinter, import end. And that's going to make life really nice for us. So if I run this now, I think our function is going to work really great. So I can type some stuff in, it prints it, and it clears it to the screen. Awesome. Let's talk about how we might really quick fix the fact that our label is disappearing. Right here, I'm going to go back down here, these are our inputs. I'm just going to, on a separate line, I'll say keep output frame size. And so we're going to call that propagate, grid propagate or pack propagate. So we want to call it on the output frame. But the output frame is not being managed by grid. It's being managed by pack. So I'm going to call pack propagate. And I'm going to pass a 0. And so now if I run this, let's just check. It should work pretty good. Hey, look at that. Awesome. Another thing that we might want to do right now is let's just change the background color of our label to red. That'll look nicer. So right in here, we'll say text. Now we'll set the background property, bg is equal to red, ff0000. I like hex color codes better. I don't know why. And this should look really good now. So let's check. Hey, cool. And it seems to be working out just the way we want it to. So pretty good. We've written our first function. That's great. Now let's just stop for a second. If we check this now, our button is linked to the make label function via the command property. So that's great. And it works wonderfully every time the button's pressed. I want to draw attention to the fact that in this example, when we call the make label function in our button definition here, we don't have parentheses, right? It's just the name of the function, make label. We just link it via the command property. So what if you have a function that maybe requires an argument to be passed, and you need to pass that information along? You sort of can't do it here. Well, we can do it a different way using lamb does. So I'm going to show you how to do that right now. Let's create a button that will count on the screen for us. So we're going to learn some interesting things here, some new things right here. So let's put a new comment here. We'll say pass a parameter with lambda. OK. So we're going to create a new button on the screen that is going to count for us. First, let's create a variable called value that's going to keep track of the number that we're counting. So value is equal to 0. And let's create our count button. So count button is equal to tkinter.button. And we're going to put this button on the input frame, because we want the user to be able to press it. And the text will just read count. And let's use the grid system. We'll put it on the screen. So countbutton.grid, the input frame is being managed by the grid system. We'll put it in the first row and column equals 0. And so we have the entry box in the first row and column 0. And then the print button in the first row, column 1. I want this button to sort of span everything. So I'm going to do a column span of 2. And we're going to put some horizontal padding of 5, some vertical padding of 5. And then I'm going to call sticky, the sticky command, to spread it out from west to east. So it should take up that whole scenario here, or that whole portion. Yeah, and I think that looks kind of nice, right? So now I can click that. But again, when I click the count button, it doesn't do anything. So I want to link it via the command property. So I'm going to come over here, command. And I'm going to set it equal to, now let's see here. I'm going to set it equal to lambda, and then colon. And I'm going to pass the function name. We're going to call our function called count up. And in here, I'm going to pass an actual value, which we call value. So I think that this is going to work out nicely. I got one too many parentheses here. So now when our command property is set, if we want to pass an argument, we have to use a lambda. We name the function, and now we pass the parameter that we're sending in. We're going to send it whatever this value is right here. So initially, it's going to be 0. So let's go in to find this function now. So I'm going to say def count up. And it is going to take a, we'll call it a number here. So perfect. And I'm just going to put a little box in here, count up on the app. Sure. So let's write this function now. Inside of the count up function, I want to alter the value of the variable value. So I define value way down here, which exists outside of the scope of the function. So any change that I make inside here to that variable is only going to exist inside here. So one of the ways I could change that is I can make the variable a global. So I'll declare it as a global variable. So I'll say global value. And when I do this, any changes that I make to this variable inside of the function are then going to exist outside of the function. So that's good. Let's make a label. So I'll say text is equal to tkinter.label. And we're going to put it in the output frame. And we're going to set the text equal to whatever the value is of the number that was passed to the function call. And I'm going to set the background equal to red here again. So it kind of blends in nicely. And then if you recall, our output frame is being managed by pack. So I'm going to pack the text to the screen. And then I'm going to change the variable value. So I'm going to say value is equal to whatever number we passed, so number plus 1. So let's run this now. And let's see. I should be able to count right on the screen now. 0, 1, 2, 3, 4, 5, 6. Perfect. Because I'm passing whatever value I put here. So if I put 5, now I'm passing a parameter 5 or an argument 5 here to the count up function. And so it should start at 5. 5, 6, 7, 8, 9, 10. Perfect. Watch what happens if I don't declare the variable value as a global here. Let me just comment this out. Oops. There we go. Any changes that I make to this variable value now only exist inside of the function. And it won't carry. So now I think it's just going to keep printing 5, 5, 5, 5, 5, 5, 5, 5. And it does. So you're going to see sometimes we have to use these. We have to make a variable global. And it's going to help us out as we move forward. OK. This is great. I think this is a good place to stop. We've written a couple of functions and linked them to our buttons. We saw how to do it with lambdas. And we now have an application that we can interact with. I'd like to do just a few more of these sort of intro videos before we dive into creating our first real application very, very soon. I hope you're enjoying the learning that's taking place here. And I can't wait to see you in that next video. Hello, and welcome back. In our last video, we saw how we could enter in information using an entry widget. In this video, I'm going to introduce another widget that allows users to enter information, the radio button. A radio button is a simple click option that can dictate how your program runs. This widget is essentially a multiple-choice button, which is a way to offer many possible selections to the user and let the user choose only one of them. So let's start by making our window and setting some properties. So I'll say import to kinter. Again, I have a new file here saved in the same directory I've been working out of. So I'll say define window. And we'll call my root window by referencing tkinter. And we'll create a tk widget. And then we'll call root.title. We'll set this as radio button basics. We'll set the root.icon bitmap as my thinking.ico. Let's set the geometry root.geometry.geometry. I don't know. Let's change it up. Let's do 350 by 350. Why not? I think that should work fine. And we'll make it so you can't resize the window. Resizable is 00. And then let's run the root window's main loop by calling root.main loop. So that'll kick the app into gear and open up that window for us. And it looks like I made a mistake. Because I spelled thicken, think, thinking, thinking. I think, is that spelled right? Man, it all looks wrong now. Let's check. There we go. Perfect. So it looks like that's running quite nicely. Wonderful. So now let's make some frames. Because we're going to be getting user input and we're going to be outputting some things onto the screen. So I'll say define frames here. Let's create an input and an output frame like we've done in our previous videos. This time, though, for the input frame, I'm going to use a label frame. So I get a nice border on that input area. So let's see. We'll say input frame is equal to tkinter. I'll call a label frame this time. And we'll put this in the root window. And I'm going to set the width equal to 350 and the height equal to, let's do 50 here. Let's try that. And I guess I can set the text, too. Why don't I say text is equal to, because it's a label frame. Why not text is equal to? This is fun. Silly. But it just shows that we can do that for a label frame, I guess. And we'll make an output frame. Output frame is equal to a. So let's just do a regular old frame. I don't care about the border here. We'll do root. We'll make the width equal to 350 still. And the height this time, let's set it equal to, when we got 300 left to work with. So I'll set this equal to 300. And we'll just place these onto the root window using the pack system. So we'll say input frame dot pack. And we'll pack this with pad x of 10 and horizontal padding of 10. And let's do output frame dot pack. And we'll do pad x is equal to 10. And then we saw this before, right? My pad y, I'm going to do 0 on the top, because I'm already getting it from the vertical padding of the input frame. And then I'm going to put 10 on the bottom. So if I run this, let's see what it looks like. OK, looks pretty good. You really don't see much of anything because the output frame, we didn't set the background color, so this is fine. And this is fun. This looks a little bit small to me. Let me expand this from 50. Let me make it, let's make it 100. And we'll set this to 250 maybe. Let's just try that. OK, I think that looks better. That looks a little bit better. So now let's put some radio buttons inside of here in the input frame to give the user some options, right? To get some input from the user. So we're going to create two radio buttons. And so let me create, I don't know, define widgets. We'll just say here, define widgets. So I'm going to create two buttons. So I'll just call one radio one. And I'm going to set it equal to a tkinter.radio button. So there's my radio button widget. And I'm going to put this on the input frame. And the text will just read print the number one. All right, and let's make a second radio button. Radio two is equal to tkinter.radio button. So there's our radio button widget. We're going to put this on the input frame. And we'll say the text will read print the number two. Awesome. And then let's see. So I've got my two radio buttons. And let's also make a print button that when we push it, will hopefully print some information to the screen for us. So I'm going to say print button is equal to tkinter. This is just going to be a regular old button widget. So tkinter.button. And we're going to put it on the input frame just like before. And the text will say print the number. OK, now let's see. Let's use the grid system on the input frame to manage the layout. So we'll say radio one dot grid. And we'll do row equals zero, column equals zero. So it's going to be in the upper left-hand corner of the input frame. But let's give it some padding. So pad x of 10, pad y of 10. Radio two dot grid. Let's put this on here. We'll do row zero. But this time, let's do column one. We'll do pad x of 10. And let's do pad y of 10. And the pad x of 10 is going to be double in between. I think that's going to look nice. It's going to space them out a little bit more. And then let's put our button, print button on the screen. So print button dot grid. Row equals. Let's put it in a new row. So row one, column zero. And I want it to be centered under both of these. So let me just run this right now if we look at the layout. I want this to be centered under both of these buttons. So in order to do that, I just have to span more than one column. So I'm going to set the column span option equal to two. And then let's give it some padding. Pad x is 10, pad y is 10. So let's see what this looks like. Look at that. I think that looks really nice. So that looks great. I think that looks really great. A few things that you notice, though, right? Both radio buttons are sort of selected. That's not good. And I can't unclick them. So they're automatically selected, and I can't unclick them. So why is this happening? Well, this is because we haven't linked these radio buttons to a variable to keep track, essentially, of what button is being pressed. To do that, we have two options. We can use integer variables or string variables. So I'm going to choose to use integer variables in this case. So to do this, we actually have to import something else from TKinter. So we're going to say from TKinter, import. Since I'm going to use integer variables, I'm going to import int var. If I was using string variables, I could import string var, depending on what type of variable we want. And we're going to use string variables coming up shortly. So don't worry. You're going to see them. So I'm just going to use some int variables here, integer variables. So right here, where my radio buttons are, let me put a comment, define radio buttons. The first thing that I have to do is initialize a variable. So I'm going to initialize a variable. I'm going to use the variable named number. And I'm going to let Python know that this is going to be an int var, an instance of the integer variable. If it was a string, you could type string var here, right? Now what I want to do is I want to link this new variable to our radio button. So here are our two radio buttons. So I'm going to link, or I'm sorry, here are our two radio buttons. I'm going to link this variable to our radio button. So I'm going to say variable is equal to number on both of these. Variable is equal to number. So now I have a certain comma. So now I have a variable that's keeping track of the state of which button is being pressed. But I also have to give the radio button a value that it will pass to the variable when the radio button is clicked. Now since our variable is an integer variable, we have to make sure that the value is an integer here. If I use string variables, I would have to make sure that the value is a string variable. So in my radio button, I'm going to set another option. I'm going to set the value option. And I'm going to set the first button equal to 1. And the second button value is equal to 2. OK, so let's check. If I run this, oh, it says number is not defined. Oh, of course it's not. See, look, I have my variable reference here number, but I don't define it until down here. So I got to move this up. That was a silly mistake. So let's try that again. All right, and so now it looks like neither one of them are clicked. I can click. That one is clicked. If I click this one, it looks like that is removed. So this is working quite nicely. So right now, when this is clicked, the variable number has a value of 1. And when this one is clicked, the variable number is going to take a value of 2. Awesome. One last thing I can do is you notice when I ran this, nothing was set initially. So upon startup of our app, I can call number dots. I can call the set method to set a specific value for the variable. So I'm going to set the variable number to 1. And now when I do this, the first rate of button should be automatically picked. And it is awesome. If I set it equal to 2, it would have been the second button. OK. So this seems to be working nicely. Our radio buttons are working nicely. Now let's write a function that's going to link our print button to some command. So in my print button here, I'm going to type in command equals. And we're going to call my command make label, because that's what we're going to be doing. And so now I just have to define this label. So let me clean this up a bit. There we go. Up here, after I define my window, I'm going to define my functions. And I'm going to say def make label. And we're just going to say print to the screen. Perfect. All right. So inside of here, let's check. What do we want to do? Well, if the user has clicked the first radio button, we want to print the number 1. And if the user has clicked the second radio button, we want to print the number 2. So we have to kind of have some conditional statements here. So if the first radio button has a value of 1, well, the first radio button is called radio 1. And the variable is the variable number. So what we want to do is we want to get the value of the variable that we have here. So we're going to say if number.get. So we're going to call the .get method on our variable. Just like we called the .get method on our entry box in the previous videos, to get the text that was in there, we can call .get on an int var or a string var to get its value. So we're going to say, if number.get is equal to 1, well, then we're going to create a label. Num label is equal to tkinter.label. We're going to put in the output frame, and the text is just going to read 1, 1, 1. Funny. Lf number.get is equal to 2. Well, then that means if the value is 2, our second radio button is clicked. We're going to call our label, numLabel, is equal to tkinter.label. It's a label widget on the output frame, and we're going to say the text is equal to 2, 2, 2. And then once that's done, we're just going to call numLabel, and we're going to pack it to the screen. We can pack it on the output frame because the output frame isn't being managed yet. So we're going to say, hey, output frame, use the pack manager. So let's check this. Let's see if this is going to work now. Okay, so if I have the first radio button selected, so the value of the variable number is 1, and I print it, and then it says 1, 1, 1. But if I click the second radio button, now the value of the variable has changed to 2. So if you come back up here on our makeLabel function, right, this conditional is not going to pass. It's going to be this one that runs, and we get 2, 2, 2. Awesome. And so we can switch back and forth, and it seems like our radio buttons are working great. Perfect. Now we could expand this to have many more radio buttons, right, instead of printing number one, print two, we could print three, print four, et cetera. So we're going to build upon this and see how to have more radio buttons and use not only intVars, but also those stringVars that we were talking about for radio button variables as we progress through these videos. I think this is a great place to stop for now. I look forward to seeing you in our next video. Hello, and welcome back to this awesome course on Python GUIs and TKinter. At this point, if you've been watching all of the tutorial videos, you should hopefully have a solid understanding of some of the basic Python GUIs with TKinter. I'd like to show you one last concept before we dive into making some full-fledged applications. In this video, I'd like to show you how we can work with various image files like PNG or JPEG. So let's see, I got a new file here. I'm saving it in that same directory that we've been working with. I will import TKinter, and let's make our basic window. So we'll create a window and set the window properties. So define window, and I'll call it root, is equal to tkinter.tk. Okay, oops, what did I do there? Root is equal to tkinter.tk, so we'll make a tk widget. We'll set the title, root.title, and we'll call this image basics. We'll put our root.icon bitmap, and we're in that same directory we've been working out of. So thinking.ico for our ICO file. We'll set the geometry, root.geometry. Let's make this a little bit bigger. We'll do 700 by 700, and I don't care if you resize the window, so I'm not gonna set the resizable property here. And so now I'll say run root windows main loop, root.main loop, and that'll kick our app into gear, okay? So always good, let's test it, let's run it, and that looks perfect. It looks great. Wonderful. So now let's first approach images with PNG files. And so we'll call this maybe the basics. So I'm gonna put a comment here and we'll say basics. Dot, dot, dot, works for PNG. Okay, so first let's go out and talk about where I'm gonna get the PNG file. I've got a PNG file stored here. Let me see if I can just find it. Those are my videos, code files, basics. So I've got a nice PNG here. It looks like a little shield from the game rocket league. Again, I'll walk you through this. This should be in the resources tab for this video, but you can go and get it from the icon archive if you just search up, oops. If you just search here rocket league or maybe just rocket, will that show it? Right here, okay. And so again, remember always check, commercial uses is allowed, public license right here. So we can use this. So that's gonna look really good. And it's a PNG file though this time. So I downloaded the PNG and you can get whatever size that you want. So that's where I got this PNG file, okay? Awesome. I'll minimize that for right now. So first, the first thing that we have to say is that you don't just put images onto a Tkinter window. So that's not how it necessarily works. It's actually a multi-step process. First, you have to create the image. Then you have to put the image onto a label or a button or some other widget. And then you put that widget onto the screen. So let's first create our image, all right? So let's create our image. In order to do this with a PNG file, we can use the built-in photo image widget from Tkinter. So I'm gonna call something, I was gonna call it my image and I'm gonna set this equal to tkinter.photoimage. Now, inside of here, all I have to do is set the file property, so file equals and then give the file name that we wanna open. So if I look here, right, it's in my same directory as my code right here, so it's just called shield. So I'm gonna set this equal to shield.png. And so you wanna include the file extension as well. So that creates the image. Now that I have the image created, I'll use that image for a label. So I'm gonna put that image onto a label. Remember, labels can be used to display not only text to the screen, but images too. So I'm going to just say my label is equal to tkinter.label and I'm gonna put this on the root window and I'm going to set the image property. Now, instead of setting the text property, right, I'm gonna set the image property and I'm going to put my image, which is the image that I created. Now that that's done, the last thing that I need to do is just pack this onto the screen. So I'm gonna say my label.pack and I'm gonna pack it right onto the screen and so let's check this out. Does this work? Hey, and look at that, it works perfect. So there's our label. Let's just see, what would happen if I, instead of trying to pack the label, if I skip that step, right, if I just made the image and then tried to pack the image onto the screen, what's gonna happen? See, it gives me an error. It says photo image object has no attribute pack. So I can't pack the image. I have to put the image onto some other widget and then pack or use grid to place that widget onto the screen. So my label, we'll go back to my label. Awesome, this is really great. Let's do the same thing for a button. Why not? Let's make a button too. So I've got the image, right? So I can put the image on a button. So I'll say my button is equal to tkinter.button, so the button widget and we'll call, place it on the root window and we'll set the image property equal to my image. And then we'll do my button dot pack. So we can put it on a variety of widgets. And so now I should have a button here below and look at what I do and I can press the button. So that's kind of nice, really great. So this works really awesome with PNG files. However, it doesn't work that great with other file types like JPEGs. And so let's see what happens. And so I'm gonna put a note here in our comment. We'll say not for JPEG. So I got to get a JPEG image. And so if I look here, I just have a picture of a cat. You can arbitrarily just go and search cat JPEG if you want, that's what I did. And tons and tons of cat images come up. Just grab one, whatever one you want. It doesn't necessarily matter. Why cats? I don't know, I like cats. Even though sometimes I complain about my cat a lot. But anyway, cats are cool. So let's make the image. So we'll say cat image. So that's step one. So we'll do tkinter.photoimage and we'll call the file equals and we'll put the file path and what did I have my named as cat? So I'm just gonna say cat.jpeg, JPEG. And then I'll make a label. So I'll call it catlabel is equal to tkinter.label. So it's a label widget. I'm gonna put it in the root window and I'm gonna set the image property equal to the cat image. All right, so that's good. And then let's pack this to the screen. So I'll do catlabel.pack. So it's the exact same thing I did with the PNG file. I'm now doing with djpeg and let's run this. And if you look here, I get an error. The error, it says couldn't recognize data in image file cat.jpeg. So that's an issue. So to work with JPEGs, we have to actually do a little bit more work here. The first thing that we're going to do is import some libraries to help us deal with this file type. If you don't have the pillow library installed, you're going to want to do that. So open up a terminal or a prompt and you would type in pip install pillow. I think is it pillow? Let me just check, pip install pillow. See it says requirements are already satisfied. So I already have pillow installed. You could install it if you don't have it here and it will install it nicely for you. So now I'm going to import this. So I'm going to say, now I don't want to import the entire library pillow or sometimes you refer to as PIL Pill. I'm just going to import a portion of it that I want to use. Pillow or Pill is the Python imaging library and it allows us to work with those other image types like JPEGs. So I'm going to say from PIL and it's all capital letters PIL. Import, we're going to import image TK and image. And these two right here are going to help us work with the different file types. So I'm going to comment these lines out. All right, I'm going to comment these lines out because they don't work. And so now we'll say using PIL for a JPEG. All right, so now let's try this. So to open the JPEG, instead of calling TKinter.photoImage, so I'm going to make cat image, instead of calling TKinter.photoImage like I did here, I'm going to use image TK. So I'm going to do image TK.photoImage. And inside of here, instead of calling like setting the file property, instead of setting the file property, I am going to call image.open. So remember we used image TK, now we're going to use image inside of here. So I'm going to say image.open. And now inside of here, I'm just going to pass the name of the file cat.jpeg. So that's how we're going to make our image now. Once I've made the image, I should be able to make my label. So I'll do cat label is equal to TKinter.label. So there's my label widget. We'll put it in the root window and we'll set the image equal to cat image. And now we'll pack the cat label onto the screen. So cat label dot pack. So note the difference here between these two methods, right? It's just this first line that's different. Instead of referencing the photo image widget from TKinter, we're going to import it from pillow image TK. And we're going to use the image.open to open our file. And that's going to let us work with JPEG. So if you look now, we've got that really nice looking cat right there. It's one fine looking kitty. Works perfect, right? That's awesome. So I'm going to use image TK to handle the vast majority of image needs when working with TKinter throughout the scope of this course. Now one last thing I want to show you in regards to images is how images work inside of functions. So let's move our code that creates our JPEG image into a function and then call that function right before the main loop. So I'm just going to take this, right? Here's our image with JPEGs. So I'm going to cut and move this. And I'm just going to come up here right after my window and say define functions. And I'll say def make image. And I'm going to paste all of that in, okay? So let me move that, move that and move that. Always good habit, I don't know. Just print an image, a little doc string, why not? We'll keep up with it. So now before I run my main loop down here, I'm going to call the make image function. So I'm just going to call my make image function, make image, so that should run and we should get a nice cat appearing and then our window should open up. So let's see if this works. Huh, so this doesn't work. The cat is gone, if you notice, right? Our image does not load, but we also don't get an error here, right? Everything else works fine. Like I can press my button, I can close this. Everything else works fine. There was no error. The reason why, and this is going to be important, it's going to save us a lot of headache later on. If you try to display an image inside of a function like I've done here, we have to make sure to keep a reference to the image by storing it in a global variable. So I have my image cat image right here. What I really need to do is keep a reference to that by saying global cat image. And so if I run this now, it should work. And let's just check. Hey, there's that kitty, he's back. So why does this happen? Well, it's important to keep a reference as a global variable because when you return from the function, and if the image is just stored in a variable that's local to the function, then that image is going to be cleaned or cleared by the garbage collector, even if it's being displayed by TKinter. Essentially, the image is just going to be removed. So a quick global call right here should fix our issue with images, and it does, which is perfect. Okay, so I think at this point, I hope you feel like you have a good understanding of some of the basics with TKinter. Now we can build on these basics by creating some powerful and interesting full-fledged applications. And these applications will not only solidify our base knowledge, but they're also going to expand and show us new widgets and new techniques and new ideas that we can use with TKinter and our Python GUIs. So I hope you've enjoyed this course up to now. In our next video, we're gonna start diving into making our first real application. So I look forward to seeing you then. Thanks. Hello, and welcome back to this free tutorial course on Python GUIs with TKinter. At this point, you should have watched all seven of our instructional videos and will be well-equipped to begin tackling the Hello World GUI app. Here is the finished product of the application. I think I kind of showed it off already. We have an entry widget and a button widget with some radio buttons inside of a frame. And then we have another frame down here, which currently just hosts an image. I can type my name into the entry widget and click the submit button to have a label widget appear down here in what we all call an output frame. Depending upon the value of our radio button widget, the label is formatted differently. So when I have uppercase selected, it looks like we are formatting it in uppercase here. This is a great, again, this is a great test of your knowledge from what you learned in our previous seven instructional videos. Now, if I go to this video file here, I have included resources for this. So I have the icon and the image that I'm using and I've also included finished code for you to work through. Unfortunately, because I wanna keep this course free here on Udemy, I have to be under a two hour limit. And so this is why I'm not walking you through this application, but I still wanted to give it to you as a way for you to test your knowledge up to this point. So good luck to you and I will see you in the next video.