ROBERT MALATE: Good afternoon, this is CS50, and thank you for coming to today's seminar. Today, we are going to cover GUI with Python's Tkinter. My name is Robert Jomar Malate and this is Tkinter. So you might be asking, what is Tkinter? Well it's a library in Python that provides a lightweight GUI, or also known as a Graphical User Interface. It's quite simple. It's not too complex so it would be a fun project to do. This is great for making your apps visual. For example, here, if you create a program that generates a random password. So let's say, for example, you call it the Random Password Generator. You would put the number of characters and then it gives a certain password. However, that's a little bit boring, but what if you could bring that to life? Tkinter provides that opportunity here and it's great for making simple Python apps such as this, where it turns from this from the command prompt to a Graphical User Interface. Now the objectives for today's seminar is-- what we're going to cover is one simple GUI building, which is basically the basics of Tkinter, where we'll learn how to insert entry fields and labels into our app. And additionally, we want to insert buttons and we want to display the results of some action, such as pressing the button. However, what we're not going to cover is advanced methods, such as including pictures or including audio or game making, because this requires another Graphical User Interface built onto Python that is separate from Tkinter. And additionally, we're not going to cover object-oriented programming. Most of the documentation of Tkinter is done in object-oriented programming. But what I want to try to do for you guys today is give you a brief introduction of how Tkinter works and what you can do with it. So for the setup, Tkinter can't run on the CS50 ide or any online ide so you're going to need to install Python onto your computer. You can follow this link here. Go to Python.org/downloads. From there, you can select Python 3 and download that. And usually Tkinter is automatically installed in there, but if it's not, what you want to do is put this in your command line-- sudo pip install tkinter-- and you should be good to go. So after you're done with your setup, you have a text editor open. Everything is all set. Let's start coding. So Tkinter. The mindset you want to have for Tkinter is think of it as a stained glass where you have the frame and inside that frame is separate pieces of glass. So for example, in this stained glass, you have the frame over here. However, you can see it's made up of multiple pieces of glass, such as this black glass here, this glass for the light saber. You can think of that analogy as a way to construct your Tkinter GUI app. Over here, you have your window, which is the frame, and in that frame is going to be separate blocks, where inside those blocks you can put your labels, your entry fields, and your buttons. So first, let's create the label. Let's create the window. So I'm going to open up my text editor and I'm going to save this and let's call this MyApp1.py. App So what do we want to do? So first, we want to of course import the Tkinter library. So what we'll do is import Tkinter. And to shorten the phrasing, we'll just say import Tkinter as tk. Now next up is we want to create the window. So how do we do that? Well we can declare a variable. Let's just call it Window. And let's set that window equal to tk.tk. So what this is saying is that the window variable now has the properties of all the stuff in Tkinter. Now what we want to do is actually make that window run but it's kind of weird how Tkinter works because it's kind of like window is now part of it, so you kind of have to call it like a function. However, there is a special function that need to call, so what you would do is put window.mainloop. And what this is saying is that you declared a window and what main loop does, it runs everything inside that window. So let's save this. [INAUDIBLE] And there you have it. You have a Tkinter window right here. This is the window you created. So this is essentially the frame that you want to create to start building your apps. However, there are some things you notice here. For example, one, there was a default size of just about a few hundred pixels. And over here, you don't have a title. It just shows tk. The next thing we want to do is try to add a title to our own. And as you can refer here to the PowerPoint, tk declares this variable as the frame. Title will input whatever title you want for the app. And Geometry sets the size in pixels of what the window will be. So let's go back to our app and let's code that in. So what we'll do is window.title and then we can put a phrase in there. And let's say this is called My App. And then we want to set the size of this window to default size so when the user opens it, it comes out as an aesthetic size. And let's say we want a square of about 400 by 400 pixels. And one thing you want to notice here is that it's between main loop and the declaration of window. The reason is because main loop kind of works like a function, where if you call it at certain places, it's going to call it but not include stuff. So for example, if window.mainloop was in line 5 instead of line 10, we would not see the title or the window would not change to the certain geometry shape you want. So let's save this. Let's close our old GUI and let's run it again. And as you can see, this time it came out to a different shape. This time, this is a window 400 by 400 pixels. And now it has the title called My App. Now we got the frame down but we want to add the pieces of glass to the stained glass over here. So what we would do is call certain arguments. We want to give it certain properties, and among the ones we're going to use today is .label, .button, .entry, and .text, where each of them take a certain argument. So what we want to do first is we're going to create a label, then we're going to create a button, and then we're going to add an entry field. Now these are not going to do anything. For example, if you press the button, it's not going to display anything, but what we want to do is just to try to see how it'll work. So let's go back to our app. And we can do-- now this is the part where you want to comment your lines of code, mainly because you want to just keep it organized because it could get messy a little bit quickly. So first, let's create the prompt. So let's call this Label and let's call the prompt Title. And what we'll do is tk.label. And we can pass in text into it. And let's say, "Hello world, welcome to CS50 and welcome to my app." App. Now the thing is, what you just did is you gave the piece of stained glass but you don't know where that piece of stained glass is actually going to go. So what you want to do is you need to declare, where is it going to go? So what you'll do is call Title because Title is the label. You want to place it on the window, so we'll do title.grid. And what we want to do is specify the column or row, but automatically, what Tkinter does, it sets it to the row 0, 0. So if you were to refer back to the coordinates here, this box here would be 0, 0. This would be 0, 1, 0, 2, 1, 0, 1, 1, 1, 2, and so on. So now that we created our label, let's go test this out. And as you can see here, now we have the window, the frame, we have the title, a certain geometry, and now we added our label that says, "Hello world, welcome to CS50 and welcome to my app." Now let's add a little more functionality. Let's add entry fields and let's add a button. So let's call this Button 1. And what we'll do is tk.button. And we want to give it some text, so maybe let's say-- let's call this button to prompt the user to say "Click me." And as I've said before, we need to place this button somewhere and we want to place it under, so we'll do button1.grid. Now here's the point I would like to remind you, that since the code is read from top to bottom and the way the grid is displayed is from 0, 0, 0, 1, 0, 2, it'll read chronologically. So since this appears first, this will be in 0, 0, this will be in 0, 1. But if we were to switch it around-- for example, if you were to put the button first, the button's going to be the first to appear in the window, then the next below that is the prompt. So we want to specify it. Let's say column equals 0 and row will equal 1. And over here, we'll do the same thing. We'll specify column 0 but row will equal 1. And as you can see here, now we added the button. Let's add the entry field next. Let's call this Entry Field 1. And we'll do tk.entry. Now the thing with Entry field, it's kind of like an HTML form or a Submit form where there's a blank box and then you type whatever you want inside it. There are certain arguments that insert it but we'll cover more on that later. So what we'll do is, now we declared the entry field, we want to place it on the grid, so we'll do entryfield1.grid. We want to put this entry field right below our button. And as you can see here, now we have our entry field inside. So that's pretty much it for the setup of the Tkinter. Now we want to try to build it up from there. So, ahead of time, I wrote some programs that display this, so let's refer to this one. App2.py. So as you can see here, this is the same thing. We're declaring a window. The title of that window is going to be My Awesome App. The geometry of that window is going to be a square of 300 by 300 pixels. Here, we're going to have a label that says, "This is CS50. Welcome to my awesome app." We're going to have an entry field there, a button, and a text field. This was the app we created. Now we want to include-- now this is for you guys to see how it looks like and how it works. But this is kind of bland. A little bit boring. So what if you say that you want to change the font of this label or you want to make this button red. So let's say we want to change the font of this to Times New Roman, maybe size 20 font, and maybe let's make the button red so the user will be more inclined to push it. Well I wrote code ahead of time for this one. This is the same exact one except it takes in extra arguments. So first, you can notice here that label has additional arguments. For example, we still have the text. However, now we have the font. And what this font is specifying is that will be Times New Roman and it will be size 20 font. Now this is not the only arguments for it. There are documentation on these but we'll refer to them later. And then also you notice on the button that it has the text "Click me" but also has bg, or background, as color red. So let's try running this app. And as you can see here, now we have some new-- our app looks a lot more creative and a lot more different. This time, it has Times New Roman font and the button is now red. So as you can see, there are a lot of arguments that you can pass on to these, and you can find these arguments at fbot.org. And here you can see a lot of new resources of the documentation they include for Tkinter. Now before we begin on making an app, let's start with the general steps. So step number zero is you want to plan out a layout for your app. As you can see here, we need to treat Tkinter as a frame, where we have the frame and we have the pieces of stained glass and we want to put those stained glass in certain places. That's why we want to lay out our app. So for example, let's say we want to create an app where it displays a greeting, it takes in your name, and it displays, hello, your name. So what we'll do is we'll add a label here, another label here that prompts the user to ask them for their name, an entry field here, a button, and below that button will be a text field that will pop out that will say the user's name and a greeting. So we planned out our app. Next is we want to create the window of our app. So let's create a new app and we can call this NewApp.py. And let's start by creating the window. So first, we want to import the Tkinter library as tk, and remember, tk is just a shorter way of saying Tkinter because normally we would have to put Tkinter.label or Tkinter.button. But using tk, we can use shorter characters. Now we want to declare the window, so we'll do window will equal tk.tk. And we want to add the title and geometry of the window, so window will equal window.geometry. Let's make it 400 by 400 pixels. And next what we want to do is add the title, window.title, and let's call this Greetings. Greetings blank. And of course, we don't want to forget the crucial process. For this to actually exist or for the window to actually pop out, we're going to need to put the main loop, so we'll do window.mainloop. And as you can notice from our previous programs where the main loop is always at the bottom, we want to push this to the bottom whenever we add new things or add new entry fields or buttons or else it won't display on the screen. And one more thing I'd like to note is that you always want to compile to see where your errors are so this will make debugging easier. So by taking this step by step, starting with the frame, then the buttons, and then the function that will run from those buttons, you'll be able to debug quicker and be able to spot any problems that occur in your code. So first, let's compile this. We'll run Python New App. As you can see, we got the window and now we got the title. Now time to add the label prompt, so we'll add label here and we'll call this Beginning Label, or Label 1. And let's make it say "Welcome to my app." And of course we want to place this on the window, so what we'll do is label1.grid. And we want to specify this, so originally in our planning stage, we said we want this welcome greeting to be in the 0, 0 position or the top leftmost corner of the map. So we'll put this in column 0, row 0. And now we want to add the next label that will ask the user for what is their name. So we'll create another label. Let's call it Label 2. And let's ask them, "What is your name?" And we are going to place it on our grid. Now we want to compile this code to make sure that it is placing at the appropriate places we want the labels to appear in our window. And we now do have a bug. Now I think I just spotted the bug and the main reason is because we misspelled. So be very careful of your spelling. And one thing that Tkinter doesn't really take note of is, for example, if I just put cat here, cat is not really a function or an argument but it will accept it. So this is really important for you to check the documentation to look for legitimate arguments that you could pass on to the function. Let's run this again. And there we have it. We have the first label at the very top leftmost corner position that says, "Welcome to my app," and the next label that says, "What is your name?" right below it. Now let's add the entry field where the entry field will go right next to your name so the user knows-- so it will look prettier and it will look a little more intuitive. So what we want to do is add the entry fields. And let's call this Entry 1. And we'll do tk.entry. Now remember, again, we're not accepting any arguments here because we want the user to put in something. So we'll just leave it blank. And we want to place that right beside the second label of "What is your name?" So it will belong in the same row but go to a different column. So we'll do entry1.grid, column 1, row 1. So it seems working fine. The stuff we wanted is placed in the right places. And for over here, we can input characters. We can even input numbers. Now let's add the button. So we'll just call this Button 1. And of course, again, we want to place it. So let's say we want to place it right below the name prompt. So "What is your name?", and right below that, we want to put the button over there. So it will belong to the 0th column and in the second row. So we'll do button1.grid, column 0 and row 2. And in that button, we want to have a prompt phrase, so let's make the button say, "Click me." Now we have the general components created of our app now. We have the labels, we have the entry fields, and we have the buttons. But the thing is, for example, if I were to just put my name, Robert, it's not actually going to do anything because the button is just a button. It just exists right there. This is the part where we're going to need to include a command argument or a function. So we're going to close this window and go back to our app. And because of the way the programs are read in a computer from top to bottom, we're going to need to put the function above the button, because if the button is the one that's going to be calling the function, we want to put the function above it. So we'll define our functions here. And let's call this first function the Phrase Generator, where it will return your name and a phrase put together. And to make this a little more fun, let's make the phrase generate random phrases that we manually input. So for example, it could say "hello," "what's up," "aloha." So first, we want to also import the random module, and let's start defining the functions. So Phrase Generator phrase. First, we need to create the list of phrases that the computer will pick from, so what we'll do is we'll create a list called Phrases and we'll put it as a list. And let's say we'll pass in three phrases. We'll say "hello," "what's up,"-- "hello," "what's up," and "aloha." And from my home island, we'll also include a phrase that's also "hi" called [INAUDIBLE]. Now what we want to do is get that phrase from the entry field. So this is the function we're going to call, is .get. So we want to store this inside a function. Let's call this Name. And we're going to convert this to a string. And what we want to get is from the entry field, so we're going to go to Entry Field 1 and we want to get whatever is stored inside it and store it in the variable name. So we'll do entry1.get. Now we already got the components. We got the list of phrases. We got the name. Now let's return this. So we're going to do some string concatenation here. We're going to call phrases. And we're going to randomly select one of these phrases, so we'll do random.randint from 0 to 3 plus name. So essentially what this Phrase Generator is doing is it has a list of phrases and you're getting the name from the entry field and you're concatenating them. So for example, for my name Robert, it'll say "Hello, Robert," "What's up, Robert," "Aloha, Robert," or ""[INAUDIBLE],, Robert." And any of those will be random. Now the key thing to focus on here is not the fact about the string concatenation or the random but this is just one of the things that you could do with Python-- with Python's Tkinter. So now we created the Phrase Generator, but the thing is, it just returns the phrase. If we just press the button-- so for example, if we were just to compile this-- and one more thing I forgot to add, we also want to add the command. What command does is give the button the ability to call any function. So since our function is called Phrase Generator, we'll leave it there. Now we're going to compile this. So for instance, if I put "Robert," it does nothing. The main reason is because-- OK, so it did return the phrase, and as you can see here from the command terminal, there was no errors. But it had nowhere to return that phrase to. So what we want to do is call the last piece of the puzzle of our stained glass of our app, which will be the text field, which will say the greeting and the user's name. So let's close our app here. Now let's define another function. Now what this function will do is it'll take the Phrase Generator from Phrase Generator and return an output-- a text field where the user can input. Similar to the entry field but just a lot bigger and can resize and where the user can change the inputs and copy and paste the inputs. So let's define this as Phrase Display, where I'll take in no arguments, and let's call-- now remember that Phrase Display has no idea of what Phrase Generator did, so we want to actually get the greeting from Phrase Generator and make it display in Phrase Display. So what we'll do is we'll store it in the variable Greeting and we're going to call Phrase Generator. And what we're going to do next is we're going to create the text field. So this is going to be a little more cryptic than usual but bear with me. This is the part where we're going to see our code come to life. So what we're going to do is greeting. We're going to call this GreetingDisplaytk.text. And what this master window is saying is that it's putting it inside the window. And the thing is, it doesn't have a specified height and size yet, so it could appear any dimensions. Usually it appears small. So we want to specify this. So let's say we'll give it a height of 10 and width of 30. And as before, we want to actually place this onto our grid, so we'll call this greetingdisplay.grid. And we want this to display right below our button so it can be nice for the user, after they press this button, they see their greeting. So what we'll do is look for the button and we'll put it in the same column but the row beneath it. Now the thing is, we're not yet done here. So we did place the greeting, but the thing is, how do we actually insert the greeting into the text field? So this is what we want to do. We'll do greetingdisplay.insert because Greeting Display is the text field and what we want to insert inside it is the greeting. So we'll do a little cryptic tk.n and we want to put in the greeting. Now let's try compiling this and running this program. I'll input my name. It still does nothing. So if we look back at our code, when we press the button, the function or the command we assigned it was Phrase Generator. However, Phrase Generator just returns the phrases, but when it returns the phrases, it doesn't put it anywhere. It's actually Phrase Display that returns it. So what do we want to do is change the command from-- instead of Phrase Generator, we want to put Phrase Display. Let's close our app. Let's compile it and run it again. Now we got our app. Big moment of truth. And as you can see here, it's a complete app, where we have our labels, we have our names, it took my name, I press "Click me," it said, "[INAUDIBLE], Robert." We can press again because this is random, because every time we press the button, it calls Phrase Display and Phrase Display calls Phrase Generator. And remember that Phrase Generator generates random greetings every time, so what you can do is just press the button again. It says "Aloha." Press it again. "[INAUDIBLE]." "Aloha." "What's up." Can we get a "Hello?" Yep, we got a "hello." Now we're back to "what's up." So let's play around with this a little more. So just to prove, let's say, what if my name was a number? Let's say it was 3.1415. It's saying, "Hello, pi," or whatever digits of pi you use. Now we skip a lot of steps over here but let's just recap what we just did. One, we planned the layout of our app, where we wanted our app to have two labels-- one in the 0, 0 position, one in the 0, 1 position-- an entry field right next to the label in the 0, 1 position. Actually, let's refer to this. So what did we just do? So first, we planned the layout of our app. So we said that we wanted this to be in the 0, 0 position, or the leftmost corner, and right below that, we want to have a label that says, "What is your name?" And right beside that label, we want to have an entry field where the user can put in any entries. And right below those things, we want to put a button. And after we click that button, we want a text field to display. So we planned the layout of our app. Next step, what we did was create the window for our app. So this occurs in lines here, where we declared the window, tk.tk, we declared the title of the window-- and as you can see here, that's greetings blank. It says "greetings blank" here. And then we also set the geometry. Now just keep in mind that the geometry is not set-- you can resize it all you want-- but this is the default geometry when the code first runs. And of course, we included the main loop in order to make this all appear. So we created the window for the app. Next what we did is declared the size and placed the labels, buttons, entry fields on the window. And we used the ideas of grids to place them. So as you can see over here and back in our code, we have a label that says, "Welcome to my app." It's in column 0, row 0 and appears so over there. And right below that, the row below it, it asks, "What is your name?" And the label also does display that. Entry fields, what we did is put it right beside the label that asks, "What is your name?" And then below that entry field, we included a button, and what that button will do, it'll say the words, "Click me," and when you click it, you run a command-- you will run the function, Phrase Display. So we did steps two and three where we placed the labels. Next, we want to connect the buttons and entry fields to one another through functions. Now this was a critical step in trying to connect my name and put it inside the entry field, so let's reflect on what we did back there. So let's say the name was pi. Entry 1. What is stored in Entry 1 is the string, pi. So let's refer back to our Phrase Generator. What Phrase Generator does, it takes a string of phrases. And this is the critical part, entry1.get. What it is saying is that, hey, Python, go to the Entry 1 field, pull whatever's in there and put it in this variable called Name. And then to make it a little fancy, we randomized the greeting so we can get different ones every time we press the button. And we did some string concatenation. Now, after that, what we did was Phrase Display, where we're going to store that concatenated string of a greeting. If it was, "Hello, pi," it'll be stored in Greeting. Next is the other critical step where we actually connected the text. So this is where we declared the text field to appear, and as you can see here, it's column 0, row 3, right where we want it. It's right below the button, because keep in mind that the button is row 2. Now the text field is row 3. And next what we did is we took that greeting and we want to insert it into that text field. So what we did is greetingdisplay.insert, tk n, and passed in the Greeting variable. So if we run this again, we get our complete app. Now Tkinter is not just limited to this and there are a lot more resources available out there. CleverProgrammer.com Programmer is one that I would recommend to try to search up more functionality for Tkinter but also just to learn a little bit more Python. And also next is fbot.org, where this is the most documented place of Tkinter-- not every single variable of Tkinter is documented here but this is the best one I've found that doesn't deal with object-oriented programming, because as one of my research says before that, Tkinter has not been well documented but this one will be the best place where you can to find the resources you need for Tkinter. So overall what I wanted to do for you guys for doing GUI Tkinter is not try to create an app that simply just generates your name, but I want to give you a tool that uses it. And I believe that Python's Tkinter is one way of doing it. I can't wait to see what you guys will do with it and I hope you have fun with it. Thank you.