 And hello everyone. Welcome to my simple to-do list app tutorial. This is written in Python 3 and I'm using the Genie editor. So let's take a look at what we're going to be doing today. So I've got a TK enter window here, and I've also I've already saved some tasks. I'm gonna go ahead and load. So I'm able to load some tasks up. I'm able to delete some tasks. I'm able to add a task. Okay, it tells me warning you must enter a task. So I enter a task here. I could say, let's see, get some sleep. I'm tired. And then so I just click add task and that goes up into my list. I can save those tasks. And then if I go ahead and delete or if I come back to the program later, I can load the tasks up again. So it's pretty simple, pretty straightforward. There is a scroll bar here that if I had, you know, many tasks going past the limit, I would be able to scroll up and down. I'll show you that in the video. So let's get started. Just so you know, this is going to take about 50 to 60 lines of code. So it's not too too complex, but there's a couple of little gotchas. So let's go ahead and write our first line. As I said before, we're going to be using the TK enter module, which we're going to be using to make the windows and the widgets and things. We're also going to be using from the TK enter module, the TK enter message box. I'm pretty sure it's a class. And yeah, that's that. So if you haven't seen any of my other TK enter tutorials, you might want to start with those, particularly maybe the BMI calculator is a bit simpler to follow. This one's a bit more complex, but I'll walk you through it step by step. So first thing I need to do is to create a window where I'm going to actually put all these things to. So I want to say root root equals TK enter dot TK and parentheses. Note the capitalization is very important. And I'm going to give my program a title. And I'm going to call this to do to do list by at Tokyo ed tech. And you can't follow me on Twitter. I do have an Instagram and but the best place to contact me is here on YouTube. So you can just, you know, subscribe or leave a message in the comments below and I will get back to you if you need some help. So that will create the window. Now, if I run this, you can see basically nothing happened, which is what I expected. Because what happens is once it gets the end, program stops. So what we need to do is the last line of our program needs to be not to root dot main loop. Okay, so I'm going to go ahead and run that again. And I can see I've got a window. And what we're going to do is we're going to start putting all of our widgets into that window. So usually when I do this type of program, I will start with the GUI because I think that's kind of gives us a little, you know, basis to put things and kind of helps us to understand what we want to do. Now you've already seen what the program is going to look like. I think I closed it, but it looks something like this. So we're going to have a list box widget. We're going to have a scroll bar. These are actually inside of a frame and I'll show you why in a second. We have an entry widget where we can actually enter information. And then we have one, two, three, four buttons that will control what our program does. And each button is actually connected to a function, as you'll see in a little bit. So when we go ahead and create the GUI, so create GUI. And first thing I'm going to do is I'm going to make a list box. And I'm going to call it tasks, because that's what I'm saving here. And this is going to be TK enter dot list box. And I have to say where it's going to go. So I'm going to put that into the root window. Now I'm going to change this in a little bit, but for now it's root window. And I need to give it a height. For now, I'm going to give it a really short height. I'm going to keep it small. I'm going to say height equals, let's just do three. And I'm going to give it a width. And this is in characters. So how many characters I want it to hold. I'm going to make that 50. And if you see my other TK enter tutorials or GUI tutorials, you know, the next thing we need to do is to pack it. Now I don't have to do it in this order. I could create all the widgets then pack or use the grid. I'm just going to do it here. It makes things easier. List box task dot pack. Now notice the names that I'm using. So I very much emphasize to my students that if you name things properly, it will make you your life easier. So I'm creating a list box. So I call it list box. The list box contains a bunch of tasks. So I'm actually going to call it list box tasks. Because that, oops, that happened there. Control Z, control Z, okay. List box tasks and I'm going to call it list box tasks. And if you haven't really programmed this type of stuff before, this is something I always recommend to my students. And they always ignore me and they always pay the price. Test it. Let's go ahead and test it. And you can see now this has changed. And now I can't do anything with it, but there is a list box widget there. And it is 50 characters wide based on this. And it is three rows, sorry, it's 50 characters wide and three rows high. So the next thing I want to add is my scroll bar. Well, yeah, let's do the scroll bar, I guess we could do that. Actually, we'll come back to the scroll bar a little bit, because that's a bit more complex. So I'm going to go ahead and make an entry task widget, because that's where we're going to put the information. And I'm going to call that tkinter.entry. It also goes into the root. Its width is also 50. And same thing, I'm going to go entry task dot pack. And I didn't put tasks because we only enter one task at a time. So all of my variable names make sense, just I think they do when I test it. So here now I can actually start typing some stuff in there. And if you recall, we had four buttons. The first one was button, add task, because that's what it does. tkinter.button, it's also going to go into the root. It's going to say text equals add task. The width of this one is going to be 48. I found that number works really well. And I need to give it a command. So this is what function is called when I run it. Now it should come as no surprise. I want it to be logical. So this is button, add task. So I'm going to name my function also add task. Now if you're used to functions, notice how there's no parentheses here. This is kind of a limitation of tkinter. If we wanted to pass parameters, we'd have to use something called a lambda. We don't need to do that here. So I'm going to go ahead and define add task. And for now, I'm just going to put pass. That's just a placeholder so that it follows the indentation pattern we require in Python. And I'm going to go ahead and pack this as well. And if you're following along, you should know that we're going to test it. So I've got my list box. I've got this. I've got add task. So I guess at this point, we've got to make a decision. Do we want to go ahead and make all the rest of the buttons? Or do we want to go ahead and try to do some of the functionality? If you haven't done this stuff before, if you're not sure what you're doing, it's probably better to kind of get the functionality working so you can see how all the different parts fit together a little bit. So let's go ahead and do add task. And let's see here. We do have quite a few things go over here. So add task. So basically what I'm going to put here is I'm going to put a task. And let's say I should call my mom. And what I want to happen is when I click add task, it will appear here on my list. So the first thing I have to do is get the task. Again, keep in mind, look at how I'm naming my variables. I didn't call it T, I didn't call it TK, I didn't call it TSK. I called it task because it represents a task. If you do this, it will keep your code much, much easier. Now, I need to get the task from entry task. Makes sense. And there is a method called get. And that will give me the text of what I've entered. And what I want to do is put that into the list box. And the way to do that is list box tasks.insert. And the thing is we have to tell it where to insert it. So do we want to insert it at the beginning? Do we want to insert it at the end? In this case, we want to insert it at the end. So to do that, we use TKinter.end. Note the capitalization. And what we're inserting is the actual task. Stop and test it. Again, beginners will just type in all the code that I give them and they don't understand how anything works. So here we go. Let's run this. So what I should be able to do now is enter my tasks. If I click add task, it should appear up here. So add task. OK, let's do it again. Add task, add task, add task, add task. Now I notice I can't scroll yet and that was intentional. So a couple of things here. Notice how what happens is I add the task and that's it. If I think about that, I'd probably only want to add a task once. So what I should do is clear the entry widget. So I'm going to go ahead and do that. I'm going to say entry task dot. And I'm going to be deleting from the zero with elements. It's the first element, but zero. It's way computers count all the way to the end. I'm going to test it. So I'm going to type here call mom and I'm going to add the task. Now you can see how it worked and now this is clear. So I'm going to click add task again. I'm going to try call mom again. So you can see how it allowed me to add an empty task. Wait, I don't want that to happen. So I'm going to use a little if statement. So if the task is not equal to empty, like nothing, there's no space here. Do this. Now, if it is empty, I want to warn the user. So TK enter message box, which we import it up above show warning. And the title, oops, the title is going to be warning. Yeah, don't have to make it so dramatic, but you can and the message is going to equal. You must enter a task. So you can see how we're building this up piece by piece. We're thinking about how we want our functionality to work. I'm going to put else here, sorry. So if it's not empty, go ahead and put the information in, delete it from the entry. Otherwise, if it's empty, we want to print a warning. So I'm going to go ahead and run that and test it. So say I'm going to type call mom, hit add task. Now I'm going to hit add task without typing anything. I've got a little warning says you must enter a task. So I go ahead and say buy new guitar. Wouldn't that be nice? And notice now there's no space. So I'm not filling in empty things. So we have the basic ad functionality working already. Look how look how few lines this takes. So one, two, three, four, five, six lines to do all that functionality. This is the power of Python. This is the power of the TK inter module as well. So I think what I want to do at this point is do the scroll bar because the scroll bar is a bit complicated. Now I didn't know how to do this a couple of hours ago. I just went and did some Googling and I found some information on how to do it. So let's do it to get to get that to work. We need something called a scroll bar. So in a lot of gooey libraries, the scroll bar will come as part of the widget already. But the TK inter module works just a little bit differently. And you need to add the scroll bar and connect the scroll bar with the widget. It's not hard to do, but you just need to do it. So what I'm going to do is I'm going to create the scroll bar and it will probably come as no surprise. I'm going to call it tasks. So scroll bar tasks equals TK inter dot scroll bar. It is also in the root window and it that's it. Actually, for scroll bar, that's all you need. You don't need anything else to go in the window. And I'm going to go ahead and pack it. So scroll bar tasks dot pack. So I'm going to go ahead and run that. See what we got here. Oh, scroll bar is not a scroll bar. OK, let's go ahead, take that out and let's try again. OK, so now you can see I've got a little scroll bar here. Now, obviously, it's not where we want it to be. We want it to be over here. So there is a an option with the pack geometry manager to put things on the side. So what I'm going to do is I'm going to say side equals TK inter dot right, because I want to go on to the right side and fill equals TK inter dot Y. And to be honest, I'm not 100% sure what that does. I'm guessing it means it fills the space, but you can play around with that and figure it out. I just know this works. So let's try it. OK, so now you can see the scroll bar is on the right. But it's it's kind of in the wrong spot. OK, so I don't want that, obviously. So one thing I can try and I don't know if it's going to work. I just thought of it right now. I'm going to go ahead and just see if the order makes a difference. OK, the order did not make a difference. OK, so that's. Oh, oh, interesting. So the order. So the scroll bar is way over here now. It does make a little bit of a difference. But the problem is we only want the scroll bar to be here and not through the whole thing. OK, so let me go ahead and close that. And what I can do here is I can put side equals tkinter.left. Kind of makes sense that there's a right. There's probably a left. So I'm going to try that and see what happens. OK, so it's just it's kind of getting worse, actually. That's not what we wanted. So what I'm going to do is I'm actually going to create a little bit of a frame. The frame is going to hold just the list box tasks and the scroll bar tasks. So I'm going to go ahead and create that first. And again, it'll come as no surprise. I'm going to call this frame tasks. And you don't have to do it this way. But if you have a long program, especially, you'll find it's really helpful if you have things named properly. And this is going to be a frame and it's going to go into the route. And then I'm going to say frame. Tasks dot pack. Now let's run that and see what happens. OK, now you can see how there's been no change and this is this is what's expected. So the difference is because I have a frame, I don't want my list box to go into the route anymore. I want it to go into my frame tasks. And same thing with my scroll bar. I don't want to go into the route directly. I want it to go into the frame. I call tasks. So let's go ahead and run that. And there we go. We basically got what we wanted. So we've got the scroll bar here and we've got the widgets where we want them. So let me go ahead and add some items here. So A, add task, B, C, D, E, F. So I've added all these items, but I can't I can scroll with my mouse, which is which is convenient. But I want to go ahead and use a scroll bar. Now, the scroll bar is just sitting there doing nothing. So what I got to do is use the following code. And this is just something I googled. I found out how to do it. I don't quite know how all of it works, but with a little bit of experimentation, I did get it to work. So I'm happy. So I'm going to say scroll bar tasks. Not config. So I'm configure configuring it. I'm going to say the Y scroll command. That's when we scroll Y, which is up and down equals scrollbar task dot set. So when I scroll on my scroll bar in the Y direction, it's scroll bar tasks set. So it's going to call the scroll bar task set method. So then on the scroll bar tasks, tasks, I need to do a little config as well. It's going to say command equals list box tasks. Oops, I made a mistake there. This should be list box tasks dot config. Sorry about that. List box tasks dot config. And this should be scroll bar tasks dot config. Sorry about that. It was list box tasks dot Y view. So I assume this is the view of in the Y coordinates, which would be up and down. OK, so that's the code. So it's list box tasks dot config. Y scroll command equals scroll bar task dot set. Scroll bar task dot config command equals list box task dot Y view. Let's go ahead and test it. And notice how it's got a little bit bigger there, which is interesting. So I'm going to go ahead and hit just add some things. B, C, D. OK, let's enter task E. Now, again, I can scroll here. Notice how the scroll bar is scrolling now. But I can also move it here. I can also click the little arrows. So now that is how we get a working scroll bar, which is pretty darn cool. OK, so at this point, I might want to just go ahead and make this a little taller. Let's say you can decide what size you want it, but I'll say let's just say we want it to be 10 tasks. If you've got more than 10 tasks, you probably got a very busy life. But yeah, so that's the basic function. At this point, we have a working to-do list. Now, it doesn't do a lot, but we want to probably add a few other commands. So we've got to add a few more buttons. So what I could do is I could just copy these. We've got three buttons to add. So we've got button add task. We've gotten button delete task. So delete task. And so we've got to change it four places. Delete task and call this delete task. And then we've got a button that is, I think, this one is load tasks from disk. So we're going to be saving it. Load tasks. And I'm going to make a method called load tasks. Again, just by keeping everything consistent, you will definitely cut down on potential sources of errors. And we're going to be just tasks. We're not loading one task. We're saving. We're loading many tasks. And then we have save tasks. I guess, technically, it could be one task, but it's probably unlikely. Save tasks. Now, if I run this, I'm going to get an error. And it says delete task is not defined. Because we made a command, but there's no method there. So we've got to go up to here. So I'm going to go ahead and just make places for that. So I'm going to say delete task. And just for now, pass. Say define load tasks. Pass. And define save tasks. And pass. So I'm going to run it and check it. OK, so I got an error there in line 22, because I forgot to put the colon. Probably you guys caught that. And OK, so I got my things. Of course, they don't do anything yet because we haven't coded them. But that's still working. And I'm going to assume the scroll bar is still working. Next up, let's see here. So let's go ahead and figure out how to delete a task. Let's see here. Just scroll through. I took some pictures of the code, so I didn't forget how to do it. OK, delete tasks. So deleting a task. So first, we got to figure out what task we want to delete. And to do this, we need the index of the task that we have chosen. So I'm going to say task index equals listbox tasks dot curselection parentheses. Curselection is the selection of the current task that has been selected. So this is just the command that you've got to use. Oh, and curselection, for some reason, it's got to be zero, index zero. I'm not quite sure why. Oh, I know why. Because what happens is you can actually select multiple items. But what we want is just one item, so that's why. So task index. And then what we'll do is listbox tasks dot delete task index. That's it. Very, very simple. So let me go ahead and run that. So I'm going to go ahead and add a few tasks. Now I'm going to go ahead and try and delete. I'm going to select B and delete it. Easy peasy. Now watch what happens. I haven't selected a task. So I'm going to go ahead and click delete and see what happens. So you can see here I've got an error. So we have to deal with this error. So what I would do, and this is something called a try accept block, is the following. Let me close that so I don't forget. So I'm going to go ahead and put here try. I'm going to index this, or indent, excuse me, accept and then I'm going to print a warning. So I'm going to go ahead and copy this. I know I've already done it once. And in this case, you must select a task. So the try accept block, what it does, is it tries this. If there's an error, it does this. So it'll try it. And if you get an error, it does the other thing. So this is a good way to stop your program from failing when there's an error. So I'm going to go ahead and add a task or two. Notice nothing is selected. I'm going to click delete. As you must select a task. So now it prevents me from trying to delete without selecting. And notice there's no error. So my program keeps running. So we're making some really good progress here. Again, we now have a working program. The last thing we want to do is saving and loading. Now, we can't load anything until we save. So we're going to do the save tasks first. And to do saving, we're going to use something called the pickle module. And the pickle module is very, very convenient. So we have to import pickle. I do have a video about this, actually, if you want to see it in more detail. But it's so simple. It's really a couple lines of code. It's just amazing what you can do with this. So to save the tasks, the first thing I need to do is I need to get the tasks. Notice again, my variable name is tasks. It's not t. It's not things. It's not items. It's tasks. It's very, very clear what I'm referring to here. So to do that, I do listbox tasks. Listbox tasks. That's the name of the listbox. There should be an underscore here. I think it's just not showing. I don't know why it does that. I think it has something to do with the font. Listbox tasks dot, where is that at? Get, and I want to get from 0 to listbox tasks dot size. Don't script the parentheses. We've got set here for the whole get method. We've got to set here for the size method. So that will give us the tasks that are in the listbox as a list. So tasks is a list. So if I said print tasks, it will do this. This is a good way of testing the code. So you understand what's going on. This is what I did earlier when I was trying to figure this out. So I click on Save Tasks. You can see down here, it's created a tuple. It's created a tuple. And we're going to save that tuple to disk. And to save, it's very, very simple with the pickle module. We're going to go ahead and use the pickle module. And we're going to use a command called dump. And we have to dump it into a file. What do we want to dump? In this case, we want to dump tasks. And we're going to put it into a file. So I'm going to use the open command. And I'm going to make a file called task.dat. Dat means data. It doesn't have to be dat. It could be something else. But this makes sense. I'm saving tasks. I'm calling it tasks. It's a data file. I call it .dat. You can call it what you want. And then I need to put wb. This means write binary. That's a bit hard to explain, but just memorize that. So I'm writing to the file called task.dat the information in the variable tasks. So I'm going to go ahead and run it. And again, so a, b, c. I'm going to save it. Now, we don't know necessarily if it worked or not. Because there's no indication that it worked. But what I could do is, oops, wrong one. I'm going to go to my desktop. I'm going to find the folder. OK. So if I go into the folder where my to-do list file is, you'll see a file called task.dat. So that's a good sign that whatever we did worked correctly. Now, until we load it, we won't know if we did it right. But that's the next step. So now that we've saved it, we can go ahead and try to load tasks. So this is amazing, the amazing thing about the pickle module. It's one line. So tasks equal pickle pickle dot load load. And this time, it's open first. It's got to be the same name, which is what we called it. And now we're not writing binary. We're reading binary. That's it. So now what we have to do is get that information into the list box. So for task in tasks. So for each task that we just loaded, list box tasks.insert at the end the task. That's it. OK. So let's go ahead and try this. And do we get the pop-up? There we go. Oh, I think I didn't close this one. There's the new one. That's something you'll see sometimes. I know my students have this problem, is because they didn't close the previous one, it's still running. So you've got to close the previous one until the new one will work. So now I'm going to go ahead and hit Load Tasks. There it is. So it pulled it out of that file for us. But there is one problem. If I hit Load Tasks again, it doubles, triples, and keeps adding them. So we don't want that. So we need a little bit of code to fix that. So basically what I'm going to do is once I've loaded this, I'm going to go ahead and clear the list box. So I'm going to say listboxtasks.delete0 to tkinterend. So that will delete everything in the list box. Oh, that's the wrong spot. Sorry. That's going to go up here. Once I've loaded the tasks, and before I add them, I'm going to go ahead and delete. So let's test it. So Load Tasks. So I'm clicking it, and nothing's happening. Now I can still add tasks. I can still delete tasks. And I can save tasks. So let's go ahead and delete, and delete, and I'm going to load. And so everything's working exactly as expected. So I'm very happy with this. Now the only thing I'll show you, there's one more thing we should probably fix. I'm going to go back to this folder where I had all that. And I'm going to get rid of this file. I'm going to just move to the rubbish bin. I'm going to delete that. So I'm going to run it again. I'm going to try and load tasks and see what happens. So you can see I got an error down here. It says File Not Found Error. No such file or directory, task.dat. So since the file does not exist, I can't load it. And it gives me an error, and then this messes up the program. So we're going to have to deal with that. And if you're paying attention earlier, you'll probably figure out, OK, we're going to do a try except block again. So I'm going to go ahead and hit try. I'm going to indent this whole thing. And in my except, I'm going to go ahead and just give a warning. So the tab, accept, and the same thing. I'm just going to go ahead and copy that, paste that in there. And the warning is just going to be something like no data file present. How about this? Cannot find tasks.dat. That's pretty useful. Let's go ahead and run it and test it. So I'm going to load tasks. Cannot find tasks.dat. So I'm going to go ahead and add a few tasks. So call mom. I'm going to say upload video. Create thumbnail and add tasks. So I'm going to go ahead and save those tasks. I'm going to go ahead and delete a few. Delete them all, I guess. And check and make sure that my load is working. And there you go. That is a complete to-do list app complete with scroll bars, saving, loading, and yeah, pretty much everything you need. So again, so you can see here, we're down to 72 lines of code. Of course, there's some spaces. There's some comments. And there's some comments up here. But yeah, it's only about 60 lines of code. So if you like what you saw, please subscribe. I do make quite a bit of content. I do have some links down below that you can either check out Patreon. You can click on Amazon links to support the channel. I do appreciate it. Or you can soon I'll be adding channel subscriptions or subscriptions, memberships. Not sure what they call it, but you get the idea. Anyway, I hope that helped. If you have any questions, comment below. And keep on coding. Take care.