Creating 10 Apps in Python [ with PySimpleGui ]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello there in this tutorial we are going to create all the guise you can see on the screen right now by using pi simple gui let me go through them really quick we start with a converter app that is quite simple but covers all the fundamentals of the module then we create a calculator with better styling and this one can update the styling dynamically then we create a stopwatch this one has even more styling and next up we have a text editor and this one can save and open files next up we have a snake because why not and after that we combine python by gui with map.lib to create an app that includes a graph a basic image editor is next and this one uses pillow to manipulate images next up we create a basic music player that can change the volume and shows a progress bar and then we continue with web stuff by building a basic weather app that gets data from google weber and finally to finish the video we are going to use opencv to detect faces and that is it by the end of this tutorial you should have a fairly good understanding of pi simple gui and how to solve more or less any problem inside of it now before i start let's talk about pi simple gui in general all this module really is is a wrapper around other gui libraries and by default the base library is tkinter all this really means is that python begui runs tkinter internally but makes it much easier to access and python bagooy does make gui development really easy most programs we are going to build require only about 50 lines of code especially if you only want some basic gui and don't want to learn a whole library python bagooy is incredibly useful also if you're just starting with guise or programming in general i think python begui is something really useful because it is incredibly easy although there are two limitations you should be aware of number one is styling and while python begui has some options to make the gui look okay this is fairly limited so we are never going to create styling that looks as good as commercial apps the other limitation is scaling python by bagui is designed for small apps if you want to make something really complex with fancy layouts you probably want to look at other libraries i guess you could be pushing it quite a bit but you would eventually run into problems but that is basically all you need for the basics although we do have to install pi simple gui and this happens either in the powershell or on the terminal and all you need is pip install python per gui or pip3 install pi simple gui and that should be all you need now before we can start with the first project there is one fundamental concept that we have to cover and that is elements now elements in pi simple gui are the core of the entire framework so if you don't understand elements you don't understand pi simple gui essentially an element can be a text it can be an image it could be a slider it could be basically any kind of element that you see in any kind of program so in the most simple term any visible thing that you see is going to be an element and this is including the window so the general frame of our app that will contain all the other elements and essentially all we ever do in python by gui is combine different elements and use that to create a more complex program and in other frameworks an element would just be a widget i honestly have no idea what i chose a different name it's literally the same thing there are also elements that are not visible and those are mostly used for layout purposes for example there is a column element that places elements inside of a column should be fairly obvious so with that we can start working on our first program a converter and this one is going to look like this a really simple app we can type some numbers in here let's say 100 then we can choose some units kilometer to mile kilogram to pound and seconds to minute and if i click on convert we get 100 seconds of 1.67 minutes and if i select different units we get different kinds of outputs and i am going to use all the basic concepts of python per gui to make this so already by the end of this part you will have a good understanding on how python page works in general but let's actually have a look how we can make this now here we are in a completely empty sheet of code and first of all i have to import pi simple gui and this happens with import pi simple gui and for this part it's really important to check out which letters have to be capitalized so the p the s and the gui all have to be capitalized and since this is kind of annoying to write we usually abbreviate this as sg which is much easier to write and now if you just want to test if this is working run the code if this is working you shouldn't see any kind of error which i don't which is a good start and now we already have to create our first element and that we create with sg.window and this is just going to create a window so this is pretty much always the starting point for any pi simple gui app and this one is going to need two arguments at the very least we need a title and we need a layout and the title is just going to be a string so in my case i want to name this a converter now for the layout we need something slightly more complex and let me put this in a separate variable that should make things a bit easier and let me give a bit of space so essentially for the layout we want a list that is going to contain other lists and let me add one list a second list and list number three and essentially what is going to happen is that each nested list so list one list two and list three each of those are going to be their own rows let me actually put them on separate lines that should illustrate the principle much better essentially we are creating a window and that is this yellow box for now the dimensions really don't matter how pyson begui creates layouts is by using these lists to figure out where the elements should be and basically what is going to happen is that each of these lists is going to be its own row so the first list here would correspond to the top row in this program the second list would be the second row and then the third list would be row number three and since our list has three lists inside our app is going to have three rows and that is going to determine the height of the window and now inside of each of these lists let me clean this one up a tiny bit to make things easier to see so we don't need these bits here essentially inside of each list we now have to place another element and let me add a couple of different elements the first one would be sg text and this one is a super simple text element that doesn't really do anything and this one only needs a single argument and that would just be a string with the text you want to display so let's call this one text another element we could place would be sg and button and button also needs a single argument which is the name of the button or the text on the button and in my case let's call this button and now on the third row we want to have let's say an input element which is called input and this one doesn't need any arguments and let me actually hide the drawings for now if i run the code now we can see that well we can't see anything and that is because we are going to need one more method before we can run all of this and that is called read so now if i run this you can see what we have just done i'm going to explain the read method in just a second but for now let me re-open the drawing i just did i guess here is best so here you can see we have one row with one element we have the second row and we have the third row so essentially all of these correspond with each other which i think makes a ton of sense it's a really simple way to organize a gui now the next question is what if you wanted to add another element on the same row and the answer here is you would just add another element inside of whatever nested list you're in so for example if i wanted to add a second element to the first row i would just add another element in here let's say one element we haven't seen yet that is called sg spin this one we are going to use in just a second actually and in here we need one list with a couple of strings so let's say item one and item two and now if we run this we can see the list selection box we have seen from the actual final program and that is essentially the system how you would create a layout in pi simple gui you basically create more lists and each list is going to be one row and then inside of each row you just add elements to create columns so essentially what we are doing in here for the layout is we are creating some sort of primitive table what you can see in here is that columns isn't really the perfect word because the columns for each row do not align so each row is independent just keep that in mind and later on we are going to learn about methods to for example span the entire width of the row with individual elements that is totally possible but for now i only care about the simple layout and this is a really good start and i guess i would really recommend you to practice this so let's do a challenge add to this layout another row and this row should contain two elements one that is a text that says hello and the other one should be a button that says test button or whatever you want to put in there it doesn't really matter all right now to add another row we have to add another list in here and i want to add first of all a piece of text so sg text and the test i think was supposed to be test but it really doesn't matter what's in here and besides that we have sg and button and this one is supposed to be called test button so now if we run this we can see another row with two more elements and we can press the button and ah right what i haven't mentioned yet is once we're pressing any kind of button the entire window disappears if you have tried this already don't worry this is normal for now what you really have to understand is this sort of layout here this is going to be essentially how we are going to create layouts for this entire video if i run this again we do have a window but if i click on any button like on this one the entire thing disappears and that's normal essentially what is happening is that we are executing the code from the top to bottom like in literally any kind of code and what python does on this line here is it waits for any kind of input and that is what this read method here does it basically reads the window and then looks for any kind of event or for any kind of returned value and as soon as we get anything returned python is going to return past this line and since we don't have anything after it the entire program is going to close so we can't see the app anymore and that is something we have to address and the way you address this is let me remove this read method here first and essentially what we have to do is to create a while true loop and only inside of this loop we want to call the read method now for that to work we have to get our window so i'm going to put the window inside of a variable and then we're going to call read on this window now this would work but do not run the code yet you would not be able to close your window which isn't ideal either and to close the window we need to understand two more concepts but for now let me implement then and then i'm going to explain what actually happened so essentially what window.read returns is an event and values and an event is the one we need to think about for now essentially events are things that are triggered by other elements like pressing on a button or closing the window and we have to add custom code to close the window which well is one line so essentially what we want to do is if event is equal to s g dot win underscore closed and if that is the case we want to break this while loop and after this while loop is over just to make sure we are closing the window i want to run window.close and now you can run the code and now i can press the button and everything is well it's not closing it's not exactly working but at the very least we get something so with that we have a basic setup for pi simple gui but now we have to talk about two core concepts of the entire framework we have to talk about events and we have to talk about values and let's start with events that's the more important part and in the most basic sense an event is triggered by a certain action and the one we have already seen is if we are closing the window so if we press the little x at the top of our window then we are calling the win closed event but essentially in pi simpagui every single element can trigger an event a good example here would be a button so if you click on any button an event is being triggered as well and the name of the event is going to be the name of the button you have pressed or rather the key of the button you don't give elements a name instead you give them a key but again this is just a different name for the same concept so a key essentially is a name for an element so for example in our case one of our buttons is called button and if we would press on that button we would trigger an event called button and i guess the best way to understand this is to actually try it and right now we have two buttons we have this button here that is called button right now and besides that we have another button that is called test button so let's run some code if this button here is pressed and to achieve that we have to check if event is equal to 10. literally all we're doing is we are using the same name here and that is how we identify the button and in here essentially let's run some basic code so button pressed if i run this code i can click on this button here and we get button pressed in the output if i click on the other button we don't get anything and since this also is a really important concept you should practice this one yourself try to call an event when this test button here is pressed and if that is the case print something else i don't know whatever you want to identify this button we have to look for the event test button and this is then going to be if event is equal to test button and if that is the case i want to print something else i can click on my button we get button pressed and i can click on test button and we get something else however now this system really isn't ideal because you might have a system where you want two buttons to have the same name let's actually try this if i name both of these buttons button let's see what happens so now if i click on the button we get well the first button gets this button pressed the second button doesn't work at all and on top of that what if you wanted to address other elements like this spin element or this input element neither of those really have a name right now we couldn't really address them if they have an event so we need a more general way to find and identify an element and for that each element has an argument we can pass in and that is going to be a keyword argument that is called key and key is just going to be another string we could call this one button1 and then let me copy all of this and let's call this button2 and now for the events down here we don't check for the name of the button instead we can check for the key of the button which is not visible to the user so we can name it whatever we want and then let's say for the other element this is button two now button one works and button two also works and this sort of system by using keys is what you see much more often essentially every single element you have in python per gui has the keyword parameter and that for some elements is going to become incredibly important and there is one convention in pyson begui that you can or cannot follow and that is that you usually name elements all in uppercase letters and then followed and preceded by a dash this is what you see most keys being called and i'm going to follow the system but you don't have to if you don't like it in my case i want to stick as close as i can to the documentation let me rename these elements here this is still going to work so we get button and something else now i guess there's one more thing that let's cover it right now right now this text element is entirely static so if i run the code i can click on my text but nothing is going to happen which essentially means that there's no event associated with this text but we can enable an event for pretty much any element and all we really need to do is add the keyword parameter enable events and set this to true and now if i give this text a key and let's call this one text now if i copy this event and change the event text to text i can print something else and let's call this text was rest and i click on the text we effectively turned the text into a button and essentially what we have done here is we have enabled events for one element that by default doesn't have events and this works for pretty much any other element as well if you check the documentation as soon as any element has this parameter you can make it run events to turn it effectively into a button and all right with that we have events so next up we have to talk about values and values are kind of similar to events except they return more information essentially in pi simple gui there are several elements that can contain values the one we have already seen is input and sgspin would also belong to this list and values are essentially there to access the information they have stored if we type something into input we want to have access to that information and this we get from values and basically what happens is that all the elements that can contain values are storing it in one central dictionary and this dictionary is called values and essentially what you do with this dictionary is that the name or the key of each element is going to be the key and then their content is going to be the value and that way you can access each value inside of this values dictionary and i guess there's one edge case where an element doesn't have a key but does have a value if that is the case then python pagoy is going to give it a key by default which is just a number starting from zero and going towards your last element and okay i think all of that is really hard to understand so let's actually visualize it here we are back in the code and let's say if i press on button one i don't want to print text i want to print these values here so i just want to print whatever values we get here and if i run the code now and i press on button we get a dictionary with two elements the first element says zero and item one the second element says one and an empty string and just to visualize what happens if i write something in this input element let's say the word raccoon and if i now press this button again now we get a 0 and item 1 and another key value pair that says one and raccoon and essentially what is happening here is that this is the first key value pair and this one doesn't have a name right now which is why pyson pegue gives it the key of zero and the value is the value that's currently being selected which is item number one right now and then the other element that we have is this input box here and this one also doesn't have a key so it gets the next highest number which is one and the content it has right now is raccoon this one here and all the other elements like text like button the other text and the other button do not appear in this list because they do not store values the only elements we have right now that store values are the spin box and the input element so only those two appear in this list i guess what we can do now is to give one of them a key let's say for the input element i want to give this a key that is called input and now if i run this again and in here let's write another random string red panda and if i now press on the button we can see now we have the input element with the associated value so this is this element here and that way you can access values essentially if you only wanted let's say the values from the input element you could just add a string after this with the key of the element you want to have and now if you run this again let's say kitten and i want to press this i am getting kitten so this is working just fine now there is one more concept that we need to make the converter work and that is updating elements essentially what that means is every element has an update method and this update method you can use to change the value that is being displayed for example you could change the text you could change the visibility and you could change a ton more values and this one is ultimately really simple let's have a look in my code let's say instead of printing the value i type into the input box i want to use this value to update the first text element this one here with the key text right now all i really have to do is to first get my window and this window i can use like a dictionary and then here i just have to look for a specific key of whatever element we want to address this text here is going to be this text which is essentially our first element on this element i want to call an update method and by default without any keyword arguments this is going to update the text now if i run this again i can write let's say another name in here if i now click the button we have updated the text information and this we can do as many times as we want we always get whatever text we type in here and this update method can do a lot of different things the other argument you could pass in here would be visible for example and if you set this to false if i now press the button the text disappears and with that we have the fundamentals of pi simple gui essentially all you need you first of all have to understand the different elements and how to place them in the layout next you need events and values and finally you need the update method and if you understand these three concepts you already understand about eighty percent of pi simple gui it really doesn't get that much more complex so what you are going to see for the rest of the tutorial is a refinement of these concepts we are mostly going to learn about more elements we are also going to learn about a few more tools for the layout and we are going to learn about more things you can put into the update method and i guess we're also going to learn how to style the app but all of these things are pretty small but all of these are going to be fairly small if you could follow along so far you are already able to make most of the apps that you could see in the introduction but all right let's actually make the converter here i am back in the code and the first thing i want to do is to remove all of the stuff we had so far so i can start with a clean ish sheet this would be the most simple pie simple gui app it's not really an app it's more like a skeleton of an app but at the very least we can see a window and i would really recommend you to try to implement the converter yourself if you have paid attention so far you should already be able to create the converter all right now first of all i have to create a layout and i want to have two rows the first one is going to be composed of an input element and besides that i want to have a spin element and the information for this spin element let me just copy it is going to be a list that looks like this so we have kilometer to mile kilogram to pound and seconds to minutes and now besides that on the second row i want to have a single text element that by default is going to say out put so now if i run out of this we already have some basic fields oh i actually forgot there's supposed to be a button in here so on the first row we also want sg button and let's say this one should say convert so now let's try this there we go now this is working now next up i want to give every single element a key so we can identify them a bit more easily every single one of them is going to get a key that is going to start and end with a dash the input i'm going to call input the spin element i am going to call units and the button i'm going to call convert and then the text element is going to be out put and i guess to make all of this easier to read let me add a few more rows here that is going to be better now we have all we need to create the app and first of all what i want to do is i want to check if the event has been convert which essentially means that we have called this button here and if that is the case i want to read out the value inside of my input element and let's store this in a separate value input value is going to be val use and in here i want to look at my input element let's print the input value i can press a number in here if i click on convert we are getting the number although right now we do have a problem i could also write random text in here and if i click on convert this one would also be used which i really don't want because we cannot convert words so we want to check if the input value is numeric and this you get with an if statement that if input value is numeric and if that is the case let's say for now we want to print whatever value we get i can type in a number this one is being printed but if i now type in a word this one is not being printed and what we want to check now let me run this again i now after i have some kind of number let's say 10 and i press the button i want to check what unit is being selected and this i get from values and since this would be a couple of fairly simple if statement we can use the match system in python so i want to look at my values inside of my units and there are a couple of possible cases i can have the first case would be the string kilometer to mile and if that is the case let me add another variable in here i want to get my input value and multiply it with 0.06214 [Music] and this should just be 0.6 not 0.06 and all this number is for is to convert kilometers to miles that's all it does and now that we have that i want to create an output string and this literally is just going to be a simple f string where we get the input value and we say let's say something something kilometer r whatever output we get and miles and now this output string i want to use to display for this output here so at the end once this match is over i want to get my window i want to look at my output field and i want to update it and the text i want to add in here is going to be the output string and now if i run this let's say i'm going to type a 10 in here i click on convert and we are getting an error the problem is that this input value right now is a string and python cannot multiply a string with a number so we have to convert this value here to a floating point number and now this should be working let's run it again let me type a 10 in here we can convert this and we are getting a pretty long value we probably want to round a tiny bit here other than that this seems pretty good now all i want to do is to round this value with let's say two decimal points so if i run this again now let's add 10 again and we get 6.21 this is feeling significantly better now all we have to do is to cover these two other use cases as well and we should be done so what i'm going to do is to copy this case two times the second case is going to be kilogram two pound and the third one is going to be seconds to minutes and for kilogram to pound we want to multiply with a different value which is going to be 2.204 and now we have to change kilometer to kilogram and miles to pounds and then finally for seconds to minutes all we need is to divide whatever number we have by 60. then the input value is going to be seconds and we are converting this to minutes and with that we are pretty much done let's try so let me add 60 in here now kilometer to mile is going to be 37 kilogram to pound is going to be 132 and seconds to minutes is going to be one so this is working really well i guess one last thing that i would like to do is that if the user doesn't add a number in here i want to print out a warning and if this else is true i want to get my output field and update the text to please enter a number if i run this again i can type in a word in here if i now click on convert we get please enter a number and with that we have our first app wasn't actually that hard the entire thing takes about 38 lines of code and we have a lot of empty space up here which is super nice to work with as a matter of fact we can actually use python by gui to create a one-line app which is something i haven't mentioned in the introduction but it's going to be another app we are going to create in here right now i only have python begui imported and what i can do is call sg.window and in here we can pass in let's say nothing for a title because we don't care about it for this one and now i can pass in two empty lists and read and if i now run this we are still going to get a window and this window you can use to display basically whatever you want so in here i could add for example sg input i could add let's say sg button and let's call this one okay and then sg let's say another button is going to be console and now if i run this we can see a pretty solid looking app written in a single line of code and even better what i can do i can wrap the entire thing inside of a print statement and now if i run this again i can type any kind of word in here if i click on ok it disappears but i do get the values returned and this is really powerful if you just want a really simple gui for like a warning or something in whatever program you have you literally only need a single line of code to make this work which is incredibly useful but alright this one is so simple it hardly counts let's implement the next proper program and that is going to be a calculator and this one is going to look like this so we have a normal working calculator nothing special although there's one interesting thing about this calculator that i can right click on the text and change the theme this is going to give me different themes i could be using with this calculator which really isn't all that difficult to implement i guess let's create this calculator alright so here we are in the program and i already have some basic skeleton if i run this code we can see a plain window that doesn't do anything right now and i guess for the calculator the very first thing that we are going to need is quite a lot of elements let me just go through what we are going to need this is going to be our entire window this one we already have it's this one here now at the top i want to have a text element then i want to have two buttons right below that and one is going to be enter the other is going to be clear and then below those buttons i want to have all of the operation keys so we have one row here for example and in there we would have 7 8 and 9 and let's say divide this could be 4 5 6 and multiplication then we have one more row this would be one two three and let's say minus and at the bottom i want to have one button with zero that is going to be a bit wider then i want to have a period and finally i want to have my plus button so that is going to be the layout we have to create and for now we just know how to place elements but we don't know how to make elements span the entire width of a row and that's a major thing we are going to learn in this section as a matter of fact this section is going to be massively about customizing and styling our gui but before we can start with that we will have to create all of the elements so as a challenge try to create this layout with the different elements and you should be creating about 18 elements in total so try this one yourself i want to start by putting the individual lists inside of individual lines that makes it easier to read now first of all i want sg text and this one by default should be empty but let's say for now this could be output on the next row i want to have two buttons so sg button this one should be saying clear and then i want to have another button so sg button again and this one should be saying enter after i have that i want to have one more row and in here we need four buttons we start with the button for seven and then let me copy it we have the button for eight the button for nine and then we need a button for the operation and in my case this one is going to be multiplication so for now we are just going to have a string in here and now i want to copy this two times so the next row is going to be the button four five and six and i guess the row below is going to be one two and three now for the operation we also need division and we need minus now we are almost done i wanted to duplicate this line one more time and now on this row we only have three elements we have the button for zero we have a period and we have a plus all the way at the end so now let's run all of this and this is looking absolutely horrendous i guess we do have a layout but this really isn't something you would want to use it just looks terrible so this is something we have to work on and i guess this is bringing us to a really important topic in pi simple gui and that is how to customize elements and in here you essentially have a couple of different choices number one is you can set a theme and this one essentially influences the colored choices so if you want a different colored background different colors for the buttons that kind of thing and besides this one we have set options and this one is much more about the size of elements what font we have how much padding we have this sort of thing and finally for each individual element we also have a lot of customization options and that one kind of combines the two previous options so for example if we have a button we could change the color in the theme and we could change the size in the options but then we could also overwrite all of this inside of each individual element and that way you have a lot of flexibility but all right i guess let's implement all of this and let's go through them one by one now to set a specific theme you need to call s g dot theme and where you call this method here is really important for now i call it before the window and after the layout you will see in a second why that really matters and in here we only need one argument which is a string and the string should give us a name of a theme one theme for example would be dark and if i run this we can see we have a different background but each individual element still has the default styling the reason for that is that all of these elements were created before we are changing the theme so all of this gets the default styling then we are changing the theme then we are creating the window so only the window is being updated now to change that all you really have to do is call sg theme before you create any kind of element or at the very least before the element you want to style so now we have a much better looking app and in here you do have quite a few different styling options another one would be called gray gray ray and this one is like an old window styling now the question you might be having now is how can you tell which themes are available and the easiest choice to get this is to just type whatever like a random string in here if i run the code now pi simple gui is giving me a random beam and shows me all the available ones and the random one it has picked for us is dark brown 7 and now if you want to pick one specific one in here you can just copy the string for example we could go with blue mono and let's see how that is going to look now this is well a more bluish font and for now the theme i would like to go with is called light gray one and if i run this we have a white background with some blue buttons but later on we are going to learn how to change the theme while the program is open but for now don't worry about it now you could also create your own theme but i'm not going to cover that because i think that's a bit more advanced but it really isn't that hard to do if you read the documentation next up we have sg.set underscore options and in here you can well set different options for the general feeling of the program a really important one in here would be the font and in the font you can basically set a font and a font size as part of one string so for example i think a font that everybody has is called calipri and for the font size let's say 40 so you can definitely tell what's going on if i run this now we have some giant text with a different font and you can set quite a few more things in here and here we have all the options that are available so the one we have just used if i can find it really quick is up here the font and well you could also change the background color input text color text color in general a lot of different things you could be working with and if you scroll down a tiny bit more you can see a bit more detail on all the individual options although i guess some information needs to be added here but that's not really that hard to add if you want to understand this just read for here and this tells you what you need to know what do i want to do in here first of all for my font i want to have the franklin font and my default font size should be something like 20. if i run this now we have the font may be a bit large let's say a default font of 14 yeah this does feel better now there is another option i want to go for and that is button element underscore size for this one we need a tuple with the width and the height and importantly here this is not pixel information instead we use the size of characters so that a width of for example 6 and 3 would be 6 characters wide and 3 characters high it's going to take you some time to get used to this but you will get there if i run this we get something weird all of our buttons are much taller but not really wider and i'm not actually sure why this is happening it might be here that the buttons are constrained by the window itself and this is actually bringing us to the third way to customize elements and that is for each individual element in here we can set some custom parameters let's start with the 7 here and what i want to do here is set a size and the size for this button i want to set to six and three and now if i run this now the button for seven looks much nicer and essentially what i want to do is set a button underscore size and this one should be six and three and now for the size i want to have my button size and copy this to almost all of the elements that we have so we need those as well and if i go a bit further those need the button size as well and this plus and this period needed two now let's try this again and we are definitely making some progress so now most of our buttons look okay but we have a couple of outliers this zero here and the clear and enter button in particular look kind of bad and basically what i want to do is that i want to have this zero span two widths of a button for clear and enter clear should take the first two buttons and enter should take the other two so essentially what we want the buttons to do is to span the entire available width on their row and for that we have a fairly simple parameter and this one is called expand x let me type it for the zero expand x should be true and if i run this now this is looking significantly better and i want to do the same thing for my clear button and for my enter button so now if i run this this is looking like a proper gui and all of the buttons still work we are going to add functionality in just a bit there is one more thing that i want to work on and that is the output should be a bit better customized and in here first of all i want to set a custom font so font and this one i want to have franklin and it should be a font size of 26 so if i run this now we have much bigger text but now i want this output to be on the right side of the gui and to achieve that we basically have two different ways of doing it first of all we could work with the alignment right now there is a box around this text that looks like this remember the element we have here is just a box that is always on the left side of the row and this box we could stretch out to cover the entire row and then inside of this new element we could tell the text to always be aligned to the center of the box this would be the first approach but there is also another approach that we could add another element to the left of the output text and tell this element to span as much space as it can and that way we will push output all the way to the right and i guess let's implement both approaches that is going to explain things quite well all right for the first approach there is one more argument we can use and that is called justification and by default this is left but i want to change this to center so we are centering the text if i run this now we can see that nothing has changed the reason being here that this output element only has a width that is about this wide inside of here it doesn't matter if the text is on the left in the center or to the right in terms of alignment because the box is only as wide as the text so where we align it is irrelevant but if we make the box wider which we would do by calling expand x and setting this to true now we have text in the center and i can set this now to right and the text would be on the right side the other approach we could take is let me duplicate this line and comment out the first one so if i didn't want to work with justification what i could also do is to add another element to the left of the text and the element we want to add here is called sg and push now if i run this we have the same result and essentially what happens now is that sg push is an invisible element that covers as much width as it can which in our case is this area here and we are going to see sg push later on but for now i am happy to stick by using the justification and expand x now finally there's one more thing that i would like to do and that is to add some padding and i think this could be a good challenge for you let me open up the documentation for the text element here you can see all the different parameters the text element has and what i want you guys to do is to set some padding for this text in my case i went with something like 10 for the horizontal axis and 20 for the vertical axis but you can set whatever you want so try this yourself alright the padding parameter is called pad and in here we need a tuple and the tuple needs the horizontal and the vertical padding now for the horizontal padding i want to go with 10 for the vertical i want to go with 20. and with that we have some more space between our output text and the rest of the buttons and i guess just to emphasize what's happening here let's set this to 200 and now we can really see what's going on and i guess now since we are still talking about styling we could talk about how to dynamically update this layout here to set a different theme and for that to work we need to make a couple of changes but let me generally talk about what we are going to do this window here we want to close when we choose a different theme and then recreate a new window with a new theme essentially what i want to do is to create a function let's call this one create window and when we create this the user should pass in a theme inside of this function we are doing all of this here so let me indent it all by one line for the theme we don't choose light gray one we just choose whatever theme was passed into this function now site options still works button size and layout are all still fine at the end i want to return sg window and now i can just copy the arguments we already have down here and this puts my entire window inside of one function what this allows me to do is call create window and the theme i had so far was called light gray one so now we should be seeing the same outcome and if i run this we do there's no change in terms of functionality so far but what i can do now is just pass in a different string in here let's say dark and now we get different kinds of windows so now what we want to implement is a menu where we can pick from different options and once we are clicking on these options we want to create a new window with a different theme and i guess for that we first of all have to implement a menu first of all i am going to need some options here so let me add a variable that i called theme menu and we need a specific format here we first need one string and that's basically the name of the menu let's call this one menu and for the second argument we need another list and this one should contain all of our options for this menu in my case that list is going to look like let me copy it it looks like this we have a list with light gray 1 dark dark gray 8 and random which means we would have four different options for this menu and i guess let me put all the arguments for a text element on separate lines so it's a bit easier to read this is much better essentially what i want to do is to add another argument in here and the argument i want is write underscore click underscore menu and in here i just want to add my theme menu and now if i run all of this again we can't really see a difference but if i right click on the text now we can see the menu and right now nothing is really happening if i click on any of the options essentially what is going to happen is that each of these elements are effectively a button so if we click on any of them an event with their name is going to be called if the event is in [Music] this list here so what i want to look for is if the event is in theme menu with the index 1 which is just going to be another list with some strings and now if that is the case let's just print event and let's see what we get i can right click and if i click on light gray one we get light gray one we get dark dark gray eight and we get random we essentially just get a string returned and now all we really have to do is to close our current window which we do with window.close right now if i just clicked on any of this we would end the application but now what we can do is to just create a new window and this happens with create window and now we can just pass in the event we just got which is going to be a valid theme for another name and now if i try this again we get different themes and if i click on random essentially what is happening is that random isn't a valid name for theme so python begui is giving us a random theme as a consequence i guess a little bit of a hack but it well it does work for now and all right with that we have all of the styling at the layout so now we can actually start working on the calculator itself and let's just go through this one by one and let me minimize the theming so we have a bit more space first of all i want to check if any of the numbers were pressed so i want to check if the event is in and in here we need all the numbers from 0 to 9 and the period let me just copy it so i save me some writing if that is the case i want to print the event so now if i run this again i can click on the various button fields and i always get the right number now besides that i also want to check if the event is inside of the operator keys and this is just going to be another list of strings that is looking like this and if that is the case let's print the event for this one so now i also get multiplication division minus and plus the two other buttons that we have is if event is equal to enter and then i want to print the event again and finally the last button is if event is equal to clear and if that is the case let's print the event as well right so now let's try all of this we have clear we have enter and we have all of the other buttons so with that we can check for different inputs and now let's start working on the first problem so let me run this again and let's say i'm pressing 7 and 8. i can individually print these two numbers but what i actually want to do is to have the output 78 so how can i combine these two numbers into a single string and in my case what i have done let me close this i have created another list and this one i called current num and for now it's just an empty list and essentially what we are doing if we are pressing any button i want to get my current number and append whatever event we get any of these numbers or the period and this number i can turn into a string so let's call it num string and all i really need in here is a string and the join method and then here i want to pass in my current number so if i print this num string and run this again i can click on 7 and 8 and 5 and we always get a longer number so now we are making longer numbers all we have to do now is to actually change the text and for that to work i actually have to reopen my create window method because in here we have to set some keys most importantly the text is going to need a key and the key i gave it is just going to be text and if you wanted to be more thorough you could set keys for all the other elements as well but in my case we don't really need it so all right now what i want to do instead of just printing this string i want to get my window and i want to look at my text and in here i want to update whatever information we have with the num string and now let's try this again and i get some output this is already working really nicely we have to work on the operators and for those to work i have created another list and this i call full operation and this is also going to be a list and now whenever we press a button i want to get my full operation and depend what is currently in the current number and this should be appended as a string so let me copy it from the num string and i just want to append this number and then i also want to get my current number and empty whatever is in there finally i want to get my full operation and append the event any of these strings here and once we have done that let's just print what we get for full operation so now i can click on seven at eight and on a plus and now on a free and whatever numbers we have another plus let's say another minus i guess this one doesn't work perfectly but you get the idea we have a string we have an operator we have another string that is a number another operator and so on although there's one thing i forgot that after we click an operator i want to empty the text field so let me copy it from here and i just want to pass in an empty string for the output field and now all we have to do for the enter button is that i first of all want to get the full operation and append what is currently in my current number so let me copy it from there and in there why have we done this let's say we are pressing 78 and then minus 10 and now if i press enter i want this 10 to be added to my full operation so if i click on enter something is happening and now what is making all of this work is the eval function it comes with python and all this really wants is a string with map operations inside so for example what we could pass inside of here is two plus two and obviously we have to print whatever we get so if i run this we are getting four python calculates this string for us this we can use and store it in a result and what we want to evaluate is our full operation although we do have to turn it into a string so essentially what i want to do is get a string and join my full operation into the string and now all i have to do is to get my window and the text element again update this and pass in the result if i type 5 multiplied by 6 i click on enter and we are getting the result this is working just fine besides that what we have to do is i want to empty full operation so if we click on anything else we're not getting some weird results and we are actually almost done the last thing we have to do is to implement functionality for the clear button and this i think could become a good challenge for you try to figure this one out for yourself if we are clicking on the clear button all the input disappears and we are essentially starting from scratch again current number set it to an empty list and i want to get my full operation and this one should also be an empty list and finally i want to get my window text let me copy it from here and set this to an empty string i can have any kind of operation in here and if i cleared we are starting from scratch and with that we are done oh i guess the one last thing i want to change is this output by default should be empty and that is happening inside of here let me empty it and now we are starting properly and with that we have a working calculator now obviously this isn't working perfectly yet and there are a few bugs but i'm not so concerned about that with that we have a calculator and with that let's start working on the stopwatch and the stopwatch is going to look something like this we have a fairly customized window and if i click on start we get a stopwatch i can also take a lab and we get information about the time and now if i click on stop we can reset the entire thing and start again and that's just about it it's not really complicated it's mostly about styling and a few more smaller things let's implement this thing here we have the basic skeleton setup again if i run all of this we can see the plane window first of all again we have to create a couple of elements let me put them over several lines and at the minimum we are going to need two rows one with the time and one with the buttons so sg text and in here let's say time for now but we're going to change this later quite a bit and besides that i want to have another row so another list and then here i want to have a button that is saying start and besides that i want to have another sg button that is going to say lab and if i run this now we have a super simple timer layout obviously doesn't look very good so we have to work quite a bit more in the customization here and first of all when we are creating this window i can pass in a few more arguments let me put all of this on separate lines as well and in here one argument we can pass in is the size and this one's a tuple with the width and the height and those are numbers in pixels so my case i want the window to be 300 by 300 pixels and now we have a much larger window what i can also set is no title bar and put this as true although do not run the app yet because you wouldn't be able to close it so in our case i want for now to use the start button to close the entire app which basically means if the event is in the list of sg closed or start so now if i run this we have a much cleaner looking setup and if i click on start we are closing the entire thing the window element has even more options you can play around with but in my case i'm happy with those besides that we can also use a theme to customize things a bit more all the way at the top i want to call sg theme and i want to pass in black in here and now if i run this we get a much better looking setup although now we do have a very obvious problem that this stuff here should be more in the center so i want this roughly to be here and for that we need a couple of things first of all in the element i can set what is called element underscore justification and in here the default is left if i set this to right we have all of our elements on the right and besides that we can add center and now all of this is in the center now how can we center all of this on the vertical axis and for that we need two more elements we have kind of already seen what to do so let me add another list and what i would like to add in here is s g and v push short for vertical push and what this element essentially does is it takes as much vertical space as it can until it finds another element so this we push here is this entire thing but now all of our elements are at the bottom which also doesn't help us very much so what we have to do now is copy this we push element again paste it at the end and now this is in the middle we have one v push element here and one v push element here and they are aware of the other elements so if there's something in the way they only push all the way up to here and from here to here there's one more thing that i would like to add and that is an x in the top right so roughly here that is closing the application and for that we are going to need an image or well we need an image and we need an image element and well let's just add it all the way at the top i want to add another row and what i want to pass in here is sg dot image and in here we just want to have a path to an image in my case in the same folder where my file is there's also an image if i open the folder we have stopwatch and we have cross and this cross i want to import all i need is cross dot p and g and if i run this now we can see the small cross all the way at the top the issue now is that this is centered in the middle whereas i want to have it in the top right and the way to fix that is well it could actually be a good challenge for you so try to place this image in the top right and see if you can figure this one out essentially all we have to do is sg and push and now the cross is in the top right i guess another thing that we could be doing is if this image has any kind of padding so pad and you could set this to zero and now we have removed a tiny bit of space i think now i actually want to use this image as a button and this could actually be a better challenge so turn this image into a button like we have done with the text a while back and this button should then close the entire window so see if you can figure this one out all we need is to first of all enable events and set this to true and besides that we also need a key and the key for this one i want to set as close and now i want to check if the event is in when closed or in close and now let's try this if i click on the x the window disappears so with that we have a reasonable setup one additional thing is the button color so these two buttons right now i want to customize a tiny bit more and i guess the text could also be customized let's start on the text actually and here the only thing i want to set is the font in my case i want to go with the font young 50. if i run this again now we have a much larger text although i think young as a font is not pre-installed on most computers you can get it from this website here it is 100 free you don't have to pay anything you can just download it and you're good to go but if you couldn't be asked literally any other font would work in here now besides that i also want to work on the buttons and in here i want to change two attributes the first one is the button color and in here we need a hexa decimal color value this one always starts with a hashtag and now we need the amount of red the amount of green and the amount of blue and each of those would be two values and the scaling here goes from zero to f so it's zero to nine and then we have a b c d e and f so f and f would be the highest value and 0 and 0 would be the lowest value if i just set f and f for red and 0 for everything else we would have a red button and we do this is looking nice and i want to do the same thing for the other button so we have a bit of consistency and now we have two red buttons and besides that i don't really like this slight bevel around the button so the white line in the top left and this you can get rid of by just setting the border with to zero and now if i run this again this thing disappeared and this i want to do for both buttons so let me paste it in here and this is looking significantly cleaner and now the last thing i want to work on is if i click on the button by default it's going to be black which well isn't ideal so what i want to do if we are pressing the button it should turn white and for that we need the button color again what we have to do is give this button color a tuple and in here let me copy this one and paste it in twice and now if i change the first one to all f's so this one would be a white color if i run this again and if i click on the button now we get a white background and we also get white text which is what i want that i can just copy this entire thing again and change the button color here as well and now if i run this we get some much nicer looking gui i guess this is getting a bit hard to read let's put all of this over several lines and that is much better let's start working on the actual timer and for that we are going to need another module and that is from time import time and all that time does is it shows us the current time or more specifically it shows us the seconds that have passed since 1970 i think it doesn't really matter what it is i'll show you in a second how it works let me minimize all the other elements so we have a bit more space although before we start actually working on this i want to give every element we work with a proper key so things are a bit cleaner now first of all for the text this one should have a key that i have called the time and don't forget the dashes there we go now the start button should have a key that i have called start stop because that's the function of the button that's going to come in just a second and finally we have the lab button and this one i just called lab now we can actually work with this so let me minimize them and now in my event loop i have to check for some events first of all i want to check if event is equal to start stop and if that is the case let me just print time and let's see what we get so if i click on start we get a very long number and if i click multiple times this number is increasing by a very small amount so i think these are the seconds since 1970 and these are the milliseconds it is a very precise timer now the actual numbers we don't care about all we care about is the time we are pressing the button and then the time that has passed since then so i want to create another variable that i called start time and this by default is going to be zero and if i click on the start button this start time should be our current time and now that we're here i want to set the timer to active so i want to add another variable let's call it active by default this one is going to be false and once we are clicking on the start button i want to set active to true and now after this button i want to check if active and if that is the case i can get my elapsed time and this i get with my current time minus my start time time here is always the current time and start time is whenever we click the button now this number is going to show us a ton of milliseconds which i don't care about so i want to round this with one number after the decimal point i can get my window and the time i think i called it and i can update this to my elapsed time and if i run this now i can click on start and nothing is happening and if i click on start again we get 0 and 0 but if i click on lab we get 1 1.9 2.6 and now it's increasing what is happening here and this is actually the problem we have seen very early on and it's this line here python by gui is waiting for anything in the app to happen so we only get past this read method if some kind of button is being pressed and in our case we can only press the start button so this one here or the lab button which we don't have in here right now now if we are clicking the start button we will set the start time to zero and then we are checking the elapsed time and then we are returning to this and not doing anything so we remain at zero and zero but if we are pressing the labs button then we don't call this event here so then we actually get a proper time so then this one is working but obviously we can't have a timer that only works if we press a button essentially what we want is that this read method here times out after a couple of milliseconds and for that purpose the read method literally has a timeout method and in here you can set the milliseconds after it should timeout in my case i want 10. so now if i run this again i can click on start and now we have a timer and i guess now let me run it again if i click on start and the timer is running but if i now click on start we are starting again from zero and if i click on lab not much is happening at all so we have to work on these two buttons all of that is going to happen inside of this while true loop in here first of all let's update the start and the lab button once we actually start the timer what i want to do is to get my window and i want to have my start stop button and i want to update the text to stop this scenario here let's say right now this is active and now i can copy this and i want to get my lab for this one i only want to make this button visible once the timer is active so now visible should be true and by default so when i create the layout this button here should be invisible i want to set visible to false and now if i run this we can only see the start button if i click on start we can see the lab button and now the start button became stop but if i click on stop well we start again but we don't really stop so we have to work on that one and essentially what that means if i click on this button i first want to check if active is true and if that is the case i want to do something for now it's going to be pass and if that is not the case i want to do something else so in the else statement for now i want to have this code here let me remove the comment it's going to be a bit confusing this code snippet here is going to be from start to active and this snippet here is going to be from active to let's call it stop and all i really want to do in here is set active to false and now i have to update the buttons themselves let me copy them from here i want to set my start stop button to reset and the lab button should become invisible again and let's run this now i can see a start button if i click on it now it's stop and lab and if i click on stop the timer actually stops and now our button says reset and if i click on reset we start again from zero although we do have to work with this a tiny bit more but for now this isn't all that bad there's one more thing that i would like to check for and that happens inside of this else statement so we already have from start to active besides that i also want to check from stop to reset let's say the scenario is my clock is active so we are in here and i click on stop now we are here that my button is stopped and we want to reset it right now this thing is happening here but i do want to have a bit more control and essentially what we have to do is figure out how to separate these different states and the easiest way to do that is to add another if statement if the start time is greater than 0 we know we already used the timer once but if that is not the case so else then we are starting from scratch here we can add some code that we have a timer that we stopped and now we want to do something else and what i want to do in here is to close the entire window and then i want to window and create a new window that's going to be very similar compared to the function we created in the last video and then again i want to set the start time back to zero now we for now at least didn't necessarily need to close the window and create a whole new one but we are going to make some changes in just a second for the lab button that does necessitate this sort of change so we want to create a function that creates a whole new window let's do it all the way to the top all i really want in here is define create window there are no arguments we need and basically all i want is to indent all of this once paste it in here and then at the end of this i want to return this sg window so let me cut it all out paste it in here indent things properly and now window is going to be create window and let's try it still works i can click on start and now if i click on stop and reset we get a whole new window that way whatever we created earlier is going to disappear now there is one more thing that we need let me actually run it again and that is the lab button if i click on lab i want to have some text below the stopwatch that says what lab i'm currently on and what the time is and for that we need to learn about a new method that is kind of important and i think if we implement this straight away let me first check for if event is equal to lab and in here what i want to do i want to get my window and i want to extend the layout and basically what that means is that we are adding another element to our currently existing layout like some text for our current lab and in here we need a container and we need an element for now the container is going to be the window itself and the element we want is going to be sg.text let's just say test although if i run this and click on lab python by gui is going to complain that this text object is not iterable what it wants is to put all of this inside of a nested list and now let's try this again i can click on start i can click on lab and now we can see test and now this is where we are recreating the entire window so if i click on stop we still have all of these labs open but now if i click on reset they all disappear because we are creating a whole new window and this is what these lines here were for but now we have a problem that all of these text elements are not centered the reason is that when we are creating in our window this element justification it only works for the elements we already have so all of these but if we add any other element after that that element is going to have the default element justification which is going to be left and to fix this we are going to need another element and let me add it straight in here what we need is called sg column and this is an element you cannot actually see it just organizes other elements it essentially places them inside of a column and by default this one needs a nested list again what we could for example do is add sg text and this would be row one and now on the next list we could add another element let's say sg text again and row 2. so if i run the code now we can see two rows and those two text elements are inside of one element essentially the column here is justified to the center but the rows inside of it are just free-flowing and what we are going to do is we are going to add elements dynamically to this column while the app is running and for that it first of all needs to get a key and the key i want to give it is going to be let's call it labs so now all i want to do all the way at the bottom instead of the window i want to target my window and in here i want to have my labs and now i am just going to add some text to it but let's try this so if i click on start now i have my lab and now the lab is properly centered and the format i wanted here should look something like this i want my lab amount let's say a one then i want a divider and then i want the time so let's say 0.7 or whatever every time we add elements this should be one row with three different elements we have let's say a one for now then i want to add another element and that is going to be sg and v separator and that you're going to see in a second what this one does and after that i want to copy my text again and this one should just say the time if i run this now i click on start and lab and the v separator is just a straight line and now we have a lab on the left and a time on the right so we just have to make this a bit more flexible let's start with the actual lab number in here after we are creating the window i want to add another variable let's call it lab amount and by default this is going to be one and now when we are creating the text down here this is going to get the lab amount and after we are doing this lab amount plus equal 1. now if i run this again i can have lab amounts that update and this is working just fine and next up i need the proper current time and for that instead of adding the time in here i want to get my elapsed time and now i can run this again i can click on lab and we get the elapsed time i can click on stop and reset and we are back to the start i guess one more thing that we do have to do is in here when we are restarting the window i want to set the lab amount back to 1. and the final thing for this one when the app is starting it shouldn't say time it should just be empty so now i think we are done let's run this again we just have to start button if i click on it we get the time i can click on the lab this is working fine as well and if i stop we have the time i can click on reset and we're good to go cool so with that we have a stopwatch and next up let's create a text editor and this one is going to look something like this we have a menu where we can open save and exit we can check the word count and we can add smileys and then we have a big field where we can type in random words and this works over multiple lines as well and if you add a smiley let's say this one it well has a smiley a fairly simple text editor and the really interesting one about it is i can click on save and now i can save the file let's save it as test now what i can do is get rid of all of this and open a file and in here i have the test i just saved and if i open this one we have the text we just typed back so an actually working text editor and i guess you can also check the word count it's fairly straightforward let's implement it and here again we have our skeleton app if i run this we can see the basic thing we always get at the start and first of all in here i need to create a layout let me put it again on multiple lines so it's easier to read and in here we are going to see two more elements the first one is called sg and menu in here we need some kind of menu layout as an argument that is not how you spell that i'm going to create that in just a second but now let me add the other elements first besides that i want to have a simple sg and text element that by default is going to say untitled and let's capitalize it this later on is going to be the document name as a matter of fact let's give it a key straight away and let's call this one dog name and finally we need one more element and that is called sg multi line which is a multiline input element and for now let me comment out the menu so we don't get an error and if i run this we have some text element and we have some input element that we can type in now for the menu we are going to need another variable and this one i called menu layout and in here we need one list first of all and then inside of this list we need more nested lists each of those lists is going to be very similar compared to the right click menu we created earlier so we first of all need the name of the entire menu let's call this one file and the second element inside of the list should be another list and in here is the content of this file menu what i have put in here is going to be a list with these elements here we have open save a divider and exit now we have a menu at the top and we have file and if i click on it we have open save and exit with a divider between save and exit and this is what we get with three dashes now besides that i want to have a few more elements let me just copy them so we have tools and this one only has one sub menu it's called word count and add is going to have smileys now what is smileys and well smileys is going to be another variable smileys it's going to look like this and let me put it over a couple of lines so it's easier to read what we have in here is again one list but inside of this list we have a string then we have a list then we have another string another list another string and another list first string is always the title for the subsequent menu so happy is going to be a title for all of these elements set is going to be a title for all of these elements and if i run this it should make more sense so now tools we have word count but in add we have happy we have set and we have other this is what i think one of the limitations of pi simple gui that the entire framework really likes to have a list with a list inside and this list contains other lists it's more or less a russian nesting doll composed of different lists which can be very confusing to work with so i feel like all of this could be simplified quite a bit by using dictionaries if you work with this yourself be ready you have to create a lot of different lists now how can we work with these lists and here the same system applies that we have seen earlier each of these strings is going to be a button all we have to check for is the name for each of these word count should be the easiest so i want to check if event is going to be word count and if that is the case let's say print for now test we have tools i check word count and we get test for this to work properly especially for the smileys we ideally want a list with all of these buttons here so we don't care about happy set or other we just care about these lists here i created another list that i called smiley events and all this really does is i get smileys with the first index that is this one here and then i had smileys with the third index and smileys with the fifth index smiley's three is this list here and smiley's five is this list at the end i guess you could make this a bit more flexible but since this is such a simple app i didn't really care so much let me minimize these things because they are taking up a ton of space before we start i really want to set the styling of this thing to something that looks a little bit better and for that i just need sg theme and in here i want to have the theme gray gray and gray and if i run this we get a very gray theme i also want to change the styling of this multiline element no scroll bar and this should be true and besides that i want to give it a size which in my case should be 40 and 30. so if i run this one now we have a much bigger textbox while we are here let's give this one a key and i call this one text box so now we can minimize the layout and not worry about it anymore now i guess we can start working let's start working on the word count we already have that one and what i want to do in here is to show a pop-up with the amount of words and the amount of characters and for that to work we first of all need a pop-up and this we get very easily all we need is sg and pop-up we are literally creating a new element on the fly and this one only wants a string let's say pop-up in here and now if i run this and i click on word count we get pop-up and if i click on ok it disappears you will see in this part especially that python begui has a couple of elements that are only really supposed to be created for a short while and then they disappear when we are opening and saving files a very similar system is going to be in place but all i want to do in here is to display the amount of words we have and the amount of characters we have for that to work we first of all have to get our full text and the full text we again get from our values and in here i want to look at my text box i guess we haven't used values in quite a while but it's just what's being returned from all the elements that can contain values let's print whatever we get from the values i want to get the full text let's run this and let me type in something random over multiple lines and now if i click on tools and word count we get something random over multiple lines so we're just reading out the values here now how can i get the character count and the word count and let's put this over separate lines first of all i want to get my word count for this one i kind of have a problem let me illustrate so first of all obviously when i count the words i want to ignore all the spaces i want to get my full text and split this one and i want to split this wherever we have a space so now let's just print the word count so i can type something random in here and on my tools i get something random and then a line break and in here we have to get rid of the line break and the easiest way to avoid this is before we are splitting this string i want to run another method that is called replace and let me split it properly and essentially i want to replace a line break with an empty space and this empty space we are then going to get rid with this split line here so now let me try this again we have test one test two and line number three if i run this now all of the elements that are surrounded by spaces are well their own words and well this is looking really good what i want to do i want to rename this word count to clean text and my word count is going to be the length of this clean text and now what i can also do is to get my character count and this one i get with the length of an empty string with join and in here i want to add my clean text and now let's print the word count so i can add test one if i click on word count we get two words and if i instead add the character count in here and run this again so test two [Music] we get five characters this one is working just fine all i have to do now is to add an f string in here that starts with words and in this f string i have my word count afterwards i am adding a line break and then i am adding my characters and in here i am adding my character count so now let's try test number three as separate words and my word count we have two words and five characters and we are done with that we have covered the word count it wasn't actually that bad now next up we can start working on adding the smileys all we really want to do is first of all like we have done with the calculator is check if we have any kind of event that is inside of this list here what that means is if event in smiley events and if that is the case i want to print that event let's try this one now i can click on add let's say other and we get that other smiley and the logic in here is going to be fairly simple now we first of all are going to extract the text from our text box then we are going to add the string for the smiley to it and then we are going to set the text of the text box to our new text and try to implement this one yourself it really shouldn't be all that hard all we have to do is first of all i want to get the current text and this we get with values again and i want to have my text box and now let's print what we get so my current text let's run this so something something something and if i click on any kind of smiley we get the text we have but i don't just want the text we have i want to create a new text and this happens with my current text plus a space and then plus the event so the text of the smiley and finally all we have to do is to get the window and identify the text box element and update this one with the new text and now we are done i can write test something in here and i can add is that smiley and there we go we have a smiley i could add a happy smiley i could add a random smiley they'll work just fine now all we have to do let me add it here is to add if the event is equal to open and for now let me add a pass in here and besides that if the event is safe we want to save and open a file let's start with opening a file that one well they're both very easy but this one should be slightly easier first of all we need some kind of file explorer to find a file and this happens with sg.pop up and get underscore file and in here we are going to need at the very least a name in my case just open this fine now let's run this and if i click on file and open we get another dialog and in here i can browse and right now we are in the file folder i have shown in the introduction and what we have in here is one file called test and if i click on open it returns a path to that file as a string and really all i want to do is to save this as a file path and there's one more thing we can add in here and that is to add one argument that is called no window and that should be true because if we're doing that we are skipping this intermediary dialog so now we go straight to the file explorer and i can click on the file and now this is being returned to file path you probably always want window true to be the case i find this intermediary window kind of useless to be honest but it's entirely up to you now what we want to do if there is a file path then i want to import this file and for that to work we need another module and this one is called from path lib import path and this comes with python you should already have it and now what i want to do is i want to get my file and run path and use the file path here now what can we do with that file and if i print this you're going to see it in a second because this new file has one particular method that is called read.txt and this should be text now let's try this i click on file and open and the test and now we get the text from the file which is type in random words multiple lines and a smiley and this is literally just a string so all we have to do now is to get the window and the text box and update this to whatever we get from file dot read underscore text and we should be done with this one at least so now file and open test and there we go we have loaded a file i guess the next thing i would like to do is to change this untitled to the name of the file and for that let me copy this line here i now want to get my dog name and in here i want to get my file path and just print this one out so let's see what we get from this so file and open my test file and now i have the full string although that's a touch long and all i really want is this last bit here essentially what i have to do is to split this string wherever we have a slash so here and then pick the last element with the index negative one i want to split this string wherever we have a slash and from the resulting list i want to pick the element with the index minus one let's try this again now i want to open a file test and there we go now we have the actual text and the file name is test.txt that was pretty much it now for the last thing we have to be able to save this file as well and that is going to happen in pretty much the same way so let me open up the opening file dialog so we can compare the two first of all i want to get a file path again and this one again we get with sg and pop up get file now in here for the title i want to have save as and i also want no window to be true again now we have to pass in another argument in here and that is going to be save underscore s and that should be true and this essentially allows us to type in a file name when we have this popup open let me actually print what we get so print a file path and let's try this so now if i click on file and save i can type in here let's say another document if i now click on save we get printed out the whole path to the folder with another document so the text we have just typed out and this is almost what we need although what i want is to add something else to this file path and that is dot txt so we have a proper file ending and now that we have that i again want to create a file with path and in here i have to pass in the file path again and now this file class also has another method that is called write text and now we have to figure out what text we want to write which in our case is going to be the content so values of the text box we can also after we save update the name of the document and this line we could actually leave just as it is because file path is now this file path here let's try this so in here i want to write some random text over a few lines and now i want to save this let's save it as doc 1 and save now we get doc1.txt and now i can delete all of this i can click open we have doc1 and if i click on open we get our text back so with that we have a fully functioning text editor that was literally it it's ultimately a really simple thing if you understand different pop-ups and how they interact this entire project is actually really simple and for the next tutorial we are going to be creating snake and this one is going to look like this we have a field without any buttons and i am using keyboard input to control the snake and other than that it's well it's snake it's not that complicated of an app i can just move around and my snake grows and if my snake moves outside of the window the entire thing ends and well let's implement all of this and here again we are in a very simple skeleton app and we have to start by creating a layout and for this one we only need a single element although i do want to put this one in a separate variable you will see in a second why that is the case but the one element we want is called sgraph and this is a canvas that we can draw on and to start this we need a couple of named arguments let me put this over multiple lines they are getting kind of long first of all we need a canvas size and for this one we need a tuple with width and height and since i want to reuse this number later on let me put it at the top i want to have some let's call it game constants and in here i want to have a field size in my case i went with 400 and now the width and the height of my game is going to be the field size then next up we have to define the graph bottom left and this is going to be a tuple with x and y and besides that we have to define a graph top right and this also has to be a tuple with x and y values what is happening here is that this graph element is well this kind of square right now that is 400 by 400 pixels wide and high and for this thing we have to determine some kind of coordinate system so that we know where we are and what i want to do is to set the origin point down here and the top right to this point here which means that for my graph bottom left x should be zero and y should be zero and the graph top right should be the field size meaning that this point here should be a position 400 for x and also 400 for y which means y is also going to be field size and there's one more argument that i would like to pass in here and that is the background color which i just want to be black and with that we have our element and now this element i want to pass inside of the layout if i run all of this now we can see the field it doesn't show anything yet but that's going to come very soon although i guess one more thing that we can do i want to set a theme so sg theme and the theme i have set is just called green and let me add a bit of white space let's run this again and we have a green window all right now before we can work on the actual snake we need to get some kind of input and for this game there are no buttons we are only checking for keyboard input which is not that hard to do in pi simple gui all you have to do when the window is created you have to add return underscore keyboard underscore events ideally spell this correct as well and this should be set to true and now all we really need is to check for certain events so if event is a certain value and now in pi simple gui every single button has a specific keyword left for example is called left and 37 and if that is the case let me just print left and if i run all of this now i can click on left and we get left and let me put those two on the same line because i want to copy this line three times and in here we have up this one has the number 38 then we have right that is number 39 and finally we have down and this is number 40. and let's change this to up right and down and let's run this again i have right down left and up isn't working because this should be up and now we have up right down and left so this way we can get all the different keyboard inputs and with that we have all we need to get started on creating the actual game and first of all what we have to work on is we have to create some kind of grid and for now let me explain what we are going to do this here is going to be our graph element so this thing here and inside of that we want to create some kind of grid that looks something like this and in this field we are essentially creating a table and in this table every single cell has a specific value for example the top left has the coordinate 0 and 0. and the one to the right of that has 1 and 0 meaning column or x value number 1 and row number 0. and let's say if we went to this cell here the value would be one and zero one and two and this is what we are going to create now we are not going to specifically create it in anything in terms of elements in pi simple gui we are just going to use some basic math to create this kind of grid now the first thing i want to know is how many cells i have in total in my case i want to have 10 and from that information we can get the cell size and this is literally just the field size divided by the cell number meaning if our entire field is 400 pixels wide and we have 10 cells in this width then each cell is going to be 40 pixels wide and we can do the same for the height essentially our cell size right now is 40 by 40. and now we have to figure out how to draw anything in there let's get started by just placing the apple that's a nice and simple one and in here i need to get some way to store the position of my apple and this in my case is always going to be a tuple and for now let's go with something random like two and four and if i reopen the drawing this two and four is the same kind of position as this coordinate system here and what that means this here is the entire width of our canvas which is this graph element here we know this is starting at 0 and goes all the way to 400 and this we have divided into 10 fields or cells so we know we have one at 40 another one at 80 and another one at 120 and so on we have quite a few more fields and now what we have to figure out is how to convert this to into a pixel information that we can place on this with and the logic here is actually fairly simple we know that if the apple position was zero we would be at position zero so here now if the position was one we know then we would want to be on this position here the 40. and this we get by multiplying the cell number with the cell size so this 40 here would be 1 times 40. and now in our case for the apple this 2 here is just going to be 2 times the cell size so 40 and that would get us to 80. so this position here really all we ever have to do is to multiply either the x or the y position with the cell size and that is going to give us a pixel position and let's actually draw one element and see what we get now in my while loop i want to clean this one up a tiny bit so we have a bit more space this is feeling better and in here i just want to draw this apple position and to draw anything on this field we first of all have to identify it and that you would usually do with window and then you would add some kind of key in here in our case our field doesn't have a key but we have stored the element inside of a separate variable and that means we can just use the field variable and work with that one so in here i could for example call the update method but for this one we are actually not going to call the update method instead what we need is called draw rectangle and in here we need three bits of information we need a top left a bottom right and a color so what python by gui wants is we have to define some kind of a rectangle by the top left and the bottom right and let me add some random numbers in here for now i want my top left to be 100 and 100 and again these are x and y values and for the bottom right let's pick the bottom right of the field which would be 400 and 0. and now we need a color let's go with red and we right now have to press something here to get to this line so again the read method we need to time out which we will have to do later anyway so let me add a timeout of 10 milliseconds here and if i run this we can see we have a rectangle which is red that's a good start and this top left position here has the value of 100 and 100 for x and y and this point down here is position 400 and 0. and the rectangle encompassed by these two points is the rectangle we are drawing which means we are just working with a pretty simple coordinate system and now all we have to figure out is how to convert this position here to something we can actually see on the window and this is going to be an exercise for you so try to convert this apple position to some pixel information we can actually see let me put this into two separate variables one i'm going to call top left and the other br for bottom right and then i'm going to pass the top left and here and the bottom right in the second one and the top left here is really easy all we need is the apple position we want to get the x value and we want to multiply it with the cell size and since we multi-tuple i'm going to add a second value that is apple position with 1 and this one is also going to be multiplied with the cell size and let me draw all of this again here we have a coordinate system and randomly let's say we are here right now and that is our top left what we now have to figure out is some point that is here ish that is going to be the top right and now this point is actually really easy to get because we know from this point we want to get one cell size to the right and one cell size down basically all we have to do is get the coordinates for the top left and then add the cell size to both the x and the y portion inside of it and then we are done which means i want to get the top left 0 and plus cell size and then we want to do the same thing for the y values as well so tl1 plus cell size and let's try this now there we go we have well one square if i now change this to let's say zero it's all the way on the left and if i change the four to a zero we are in the bottom left point with that we can place an apple now this logic i want to reuse quite often and as a consequence let me place all of this inside of a function and let's call it convert position to [Music] excel and all we have to pass in here is a cell and then let me copy all of this we are getting a top left and the bottom right and we are getting that from this cell and once we are done we are returning the top left and the bottom right so what i can do down here now is get my top left and my bottom right and call my convert function and then here pass the apple position and we get the same result and now we can minimize this and it's working really well and now that we have that let's actually create the snake that's going to be the center piece of the entire project and in here we are first going to create a snake body and the snake body is just going to be a list and by default there are a couple of values inside and by values i mean two bolts they look like this the first value is always the head of the snake and then to the left of that we have one body part and another body part basically our snake is just going to be a list with a couple of tuples that work exactly like the apple and besides that we also need directions and this is going to be a dictionary that looks like this in here for example we have left and if we have left we are going one cell to the left and zero cells up or down and if we have up we are moving zero cells left or right and we are moving one cell up and let's actually draw the snake or the snake body to be more precise this is going to happen in the while loop again and let's actually add a comment here to draw the snake and what is going to happen here is four part in snake body which means that we are going through these three tuples right now and for each of these tuples i want to get a top left and a bottom right and this i get with my convert position to pixel and i want to pass in the part in here and now that we have that i want to get my field again called the draw rectangle method pass in my top left my bottom right and for the color let's go with green and let's run this and we can see the snake although there's a problem right now that i want the head of the snake to be yellow and the rest of the body should be green and for that to work we have to figure out which one is the first element inside of this list and that we can get fairly easily all we need is the enumerated method and this one is going to return an index and then the content of this list here and now i can set a color that i actually want to use in here and the color is going to be yellow if the index is equal to zero and if that is not the case it should be green and now let's try this now the head of our snake is yellow now next up we have to move that snake and for that we need two parts first of all we need some kind of repeated timer and then we have to use that timer to move the snake in our direction and for the first part the timer we have already seen the time module and this i want to use again which means from time import time and now before we are starting the while loop i want to get the start time which is just going to be time and then inside of the while loop i want to get something like time since start and this would be my current time minus the start time and then i can add an if statement that if time since start is greater or equal than 0.5 so half a second and if that is the case i want to set my start time to my current time and then all of the drawing is going to happen inside of that if statement and now if i run out of this we can't really see a difference because all of this is drawn in the same position every single time which is not particularly helpful so we have to figure out how to move the snake and let me draw the logic here once again we have some kind of coordinate system with some cells inside of that let me draw a few more actually we're going to need a couple and right now our snake body occupies three of these cells and let's say my snake is in this cell in this cell and in this cell and on top of that i also have one of these directions for simplicity let's assume we have the up direction selected right now which means in our game we want to move the head of the snake up one cell and we want to move the last bit of the snake to this position here and how this logic is going to work is we first of all create a new head in this position and this position we get by getting the head and towards that we are going to add the direction and if i use the numbers in our project we know that the head of our snake is in position four and four and the direction we have right now is zero and one and if we add those together we get four and five which is this cell here and that cell is then going to be our new head but now the trick is we are not going to delete this previous cell this one stays exactly where it is what we are going to delete instead is this cell here at the end so this one gets deleted and now we are done we have our new snake we have a new head position and we get rid of the last element and the new last element is now in this position here and all of this let's do it first thing in this if statement i want to get a snake update and in here first of all i'm going to need a new head and the new head is just going to be an x and a y position and for the x position i want to get my snake body and i want to get the first element if i scroll up a tiny bit the first element would be this right now and we only care about the x part for now which means from this first tuple i want to get the first element and to that i want to add the first element of whatever direction tuple we have if this is again up we want to get this first element and this direction i'm going to store in just a second in another variable called direction and this is going to be one of these two builds and in here i just want to get the first element and now we have the x value i can copy all of this and for the y value all we need to do is to change this to one and for direction we also care about one and the next important thing is we need a direction and this we need right at the start so in here i want a direction and this we get by looking at our directions and then here we can pass in for example up now we have a new head what i now want to do is to get my snake body and insert this new head which means at index 0 i want to have my new head and then i want to get rid of the last element of the snake body which we get with snakebody.pop and now if i run this we have a moving snake but it's well the snake keeps on growing and the reason for that is not that the snake is actually getting longer the problem is that all of these elements here are being drawn once but then we never get rid of them essentially what happens is we are drawing one frame and then we are drawing another frame on top of it the second time this timer here runs and in our case we are never clearing this entire drawing we are essentially drawing on top of the previous frame which means we can still see the past body parts of the snake and that we can get rid of quite easily all we have to do before we draw anything i want to get my field again and i want to draw a rectangle and in here i want to go from position 0 and 0 to position field size and field size this is covering the entire field and this entire field i want to fill with a black color and now if i run this we have a moving snake and really all we are doing in here we are first positioning our elements with all of this code then we are drawing a black frame and now this apple drawing here should happen afterwards this is becoming important later on and really all that's happening in here is we are first getting some keyboard input then we are using that input to place certain elements then we are drawing a black field and then we are filling this black field with our elements and this is very simple game logic if you have ever used something like pie game this should be very familiar to you if you want to learn about pie game by the way i have made a really long tutorial on this as a matter of fact i've made tons of tutorials on pie game but well this is all we need for the basic game now all we have to figure out now is how to get the direction from the keyboard input and this is well let me just copy this line here and we are already getting keyboard input so now instead of printing the direction i want to set the direction and i guess i can copy paste all of this in here because all we need is left and we need right and then we need down and now if i run this i can control the snake this is working really really well obviously right now the snake has no collision with the apple whatsoever but let's work on that which means what i want to do is add another section in here and let's call this one apple snake collision and to check if these two are colliding all really need is to know if the upper position and the head of our snake are in the same cell so if my snake body and the first element is equal to my apple position and if that is the case i want to get a new apple position that we don't have yet and besides that i want to define another variable called apple eaton and set this to true so we know our snake has just eaten an apple that is information we need in here in just a second and i guess to have this variable ready for the apple here by default apple eaton is going to be false and now what we need is to figure out a new random apple position and this i want to do in a function let's call it place apple doesn't need any parameters and in here all i really want to do is to get an apple position and this is going to be a random x and a random y and since we now need random values we have to import from random import rand int and for these values i want to get a random integer that starts at zero and goes all the way to my cell number minus one because if we have ten cells the highest number here should be a nine and since our field is a perfect square i can just do the same thing again and with that we have a random x and a random y value but there is a problem with all of this right now and that is that this random position could happen exactly on the snake which would be kind of awkward i suppose so what i want to do is while the apple position is in the snake body and if that is the case or while that is the case i want to assign a new output position which basically means we are creating a new upper position we are checking if this apple position is inside of the snake body and as long as the upper position is inside of the snake body we are creating a new apple position and that way eventually we are getting an apple position that is on the field but not on the snake and now i can return the upper position [Music] and we are done as a matter of fact when we initially place the apple i want to run this function already and now when our snake has eaten the apple i want to place this apple again so let's try this now and we get an error because this should be rand int now if i run this our snake is moving and if my snake head touches the apple nothing is happening so something went wrong let's check the apple collision oh and i realized this shouldn't be apple it should be up the position now let's try it again and now this is working cool let's try it again and yeah this seems to be looking really good one last time and yeah this is working alrighty now what we have to do next is to actually grow our snake after we have eaten an apple and the logic for this one is actually remarkably simple because all we really need to do is if our snake has eaten apple we don't want to get rid of the last element and to understand how that works let me reopen the drawing and let me give some space what is happening in here is we are right now moving the head and then we're getting rid of the last element but really all i need to do if the snake has eaten i don't want to get rid of this last element and that means my snake is getting a new head so it is growing but we are not getting rid of the last element so we never lose the last bit and as a consequence we are getting a new hat so the snake is growing but we're not getting rid of the last bit so this snake isn't shrinking at the end and this we only want to do for one frame so well once we have that we have grown the snake which means all i need to do if not apple eaten then i want to get rid of the last element and once that is the case i want to set apple eaton back to false although this apple eaten should not be indented and now let's try this and we are eating an apple the snake is growing for one cell and this is working really well one last try we get one larger cell nice this is working indeed there is only one more thing that we are going to need and that is to check def meaning if our snake is going too far to the left too far to the right too far up or too far down and all i have to check in here is the head of my snake so snake body zero and for this snake for now i want to check the x part and in here all i really have to check if this is between zero and between my cell number -1 and if that is the case we know we are inside of the field but if that is not the case i know we are outside of the field and now i can do the same thing for the y part let me put it on a second line so we want to check if the x part of the head is not on the field or if the white part is not on the field and that would check if our snake has left the window let's try and if either of those is the case i want to break the entire loop and end the game and there we go the game has ended now there's one more condition we have to add in here let me add another ore and that is if the head of the snake is inside of the body of the snake which we can also get very easily so snake body zero is in snake body from one to the end and now i guess i can just go in a different direction and it's going to end so i just pressed up while our snack was going downwards and that killed the snake i guess this is something that shouldn't be possible in the actual game but that's something you can implement yourself but well with that we have the entire game it took about 80 lines of code and really wasn't all that bad to implement and for the next part we are going to be creating a graph app that's the best name i could find essentially what we will make looks like this we have a table at the top and a graph at the bottom and in the middle we can add some numbers and let me add a few in here and then you see how it's going to work it doesn't really matter what i type in here as long as it is a number complete a table at the top and the graph at the bottom correspond to each other and that way collecting data should be fairly simple i guess especially if you're a scientist this could be super useful but in general what i want to focus on is the graph at the bottom and what we are going to do is to combine pi simple gui with matplotlib which is the default library in python to graph basically anything and since this one doesn't come with python by default we have to install it which means either in the powershell or in the terminal you have to type pip install matplotlib or pip3 install matplotlib and the rest should happen by itself and once we have that let's have a look at the code and here is what i have so far it is the skeleton app we have seen a million times by now as always let's start with the layout and i want to put this over multiple lines and on the first line we need a new layout and this one is called table and in here we need a couple of arguments first of all headings the argument you want to pass in here is a list and the list has to be as long as the amount of columns you want in my case that is 2 meaning i have observation and i have what i called results and besides that we need values and values i later want to reuse so i'm going to put those in a separate variable let's call them table content and this is just an empty list for now which i want to pass in here and now we can run this and we get a very basic table although i do want to make some changes for the styling and that means i want to expand x and set that to true and i want to hide the vertical scroll and this should also be true and since this is getting quite long let's put it over multiple lines so it's a bit more readable that is feeling much better and for the final argument i want to give this table a key and let's just call it table we have our first row if i run all of this now i have a table that i can move around a tiny bit not particularly useful but you do you the other element i want to add is going to be well it's two elements actually i want to add an input element and this one needs a key so let's give it a key of input and this one i want to expand x and set to true and then besides this input element i also want sg button and this one is just to submit things i'm not going to give this one a key because we just have a submit button and if i run all of this now we have a table it doesn't really do anything yet but let's work on that or i guess the one thing we can do before we add functionality is to set a theme in my case i want to go with the theme dark teal six and this one looks like this what i first of all want to do is if we are clicking let me open the app if i type a number in here and click submit i want to add a value to this table and the format i want to have is that observation should be something like 1 2 3 4 5 and so on for each observation we get a result which is going to be the number down here for 1 this would be 32 for 2 would be any other number could be i don't know 10. so when we update the table i want to get a number pair and the table is basically designed to work with that let's first of all check for the submit button if that is the case i want to get a new value and this new value we get from values and in here i want to look at my input field which is this input field we have just created and now that we have that we want to check if this new value is numeric and now that we have that i want to get my window and the table and in here i want to run the update method and now to update the table we need a list that is going to contain other lists and for an example let's say we have 1 and 10 in one list then we have another list that says 10 and 12 and a third list with three and zero and before i run this this should be an equal sign let's run this now and if i click on submit and i type a number in the field and i click on submit now we have 1 2 3 and 10 12 and 2 which are the numbers we have down here in the list we just created in here and then here again piscemba gui really likes to have a list that contains other lists it's a really recurrent theme for the entire framework what i want to do to make this interactive could actually be a really good challenge try to figure out how to make this entire thing interactive that when we are pressing the submit button then we are adding a new value to the table and the value we actually add comes from the input field so this field here i don't want to have values in here instead i want to pass in my table content and before we're updating the table i want to get my table content and append something and then here we need a list with two values we need the observation and we need the result the result is the easier part all i really want in here is the new value although this number i want to turn into a floating point number because right now it is a string which we couldn't really work with the observation is well it's not that much more difficult all we really care about is the length of the table content and to that value i want to add a 1. now why does this work and essentially think of it like this if our table content is a list that right now has zero entries it's completely empty if that is the case then the first value we want to add is going to be a one which essentially means we always want the length of the list plus one which is what i have done down here this should actually work let's try i can press a 1 123 a longer number ah and we do have a problem here that after i click submit i am not emptying this field but the rest still works just fine and i guess now let me copy this line here i want to look at my input field and i want to empty this one and now let's try this again so i have a few more numbers and this seems to be working just fine and now we have to work on the actually interesting part in this and that is the graph at the end and first of all to add a graph we have to add another element and this is going to be an sg canvas and this one doesn't need any specific arguments but i do want to give it a key that i call canvas and if i run this now we cannot see any kind of difference because we have to give this canvas some kind of value and for that we need an actual graph and for that we need the graph which means we have to import two things first of all i want to import matte plot lip and besides that we need a longer line let me type it first and then explain we need from matte plot lip dot back ends dot back and underscore d k a g g i want to import bigger canvas b k a g g and pay close attention to the capitalization here the f the c the t and the a all have to be capitalized what does all of that mean matplotlib is the easy part that well it's a graphing module essentially and what we are doing in the second line is we are importing some backend functionality that connects matplotlib to tkinter and tkinter is the basis for pi simple gui and this is basically what we need to connect the two and let me add another section here that i call matte plot lip and first of all we have to create a figure which is usually called fig in maple lip and all this means we need maple lip dot figure dot figure with a capital letter and then we need a figure size and in my case i went with five and four now after that i need this figure and add a sub plot and this subplot needs three numbers in my case i go with one one and one and that is for the position of this subplot on this figure essentially how matlab lip works is that a figure is just an empty field so the figure we get here is just this yellow rectangle and then on this yellow rectangle we need to add subplots a subplot could be here could be here and each of those have their own coordinates and then inside of each subplot you add the actual graph meaning that one subplot could be a line graph another subplot could be a bar chart and then a third subplot could be a pi chart and this one one and one gives us basically a default position in here if you know maple little bit better this should be fairly simple and now on the subplot we want to create an actual graph and the easiest one here is called plot and for this one we want x and y values in my case i want this to be empty so i'm going to add empty lists here and now if i run this we cannot see any difference but there's no error which is at the very least something and essentially what we have done now is we have created a figure by itself what we now have to do is to connect this figure to this canvas here and for that we need three lines of code first of all we need to create a figure canvas agg and for that we need the figure canvas tkag and this one needs a figure so the figure we just created and then the element in pi simple gui which in my case is going to be window the canvas and on this we have to get tk canvas and once we have that i want to get my figure canvas agg for the draw method and finally i have to call it one more time get underscore tk and widget and call the pack method and now we have two windows that was not intended but at the very least we do have a graph but we do want to connect them and the reason is pi simple gu is actually giving me an error in some form that i forgot to finalize the window and the essential problem here is that we have a window and we are adding something to that window before we are calling the read method so we have to make sure that we set finalize to true and now let's try this again now this is working this is looking much better although obviously there's no connection between the table and the graph right now but we have something and to connect the two i want to create a function let's call it update figure in here i want to pass in some data now what we have to do in here is to first of all get the access and an axis is going to give us the subplot we have just been working with and pretty much what we want to do we want to get the access and pick the first element inside of that which is going to be our subplot and now we want to create a new plot and now this plot is going to need x and y values and some styling and for matplotlib here we can add something like r and dash which means that the graph is red and the points are connected by lines again here if you know more about map.lib this should be really easy to implement and now we need x values and we need y values and these values we are going to get from our data and our data is going to be the table content and in here i am going to use list comprehension and for the x values i basically want the first item inside of every nested list inside of the table content let me actually explain this by drawing that might make more sense this table content here is one long list with a few lists inside let me just draw three in there each of those lists has two values we have the observation let's call it o and we have the result we could for example have a one and a ten in here then we have two and twenty and three and i don't know 15. and what we want for the x values is this value this value and this value essentially what i want to do in my list comprehension is i for i in data and this i right now would be the entire list or the entire nested list to be more precise which is not what we want and to only get the first value i want to use indexing to get the first value and this is always going to give us the first element inside of each nested list next up we can work on the y values and we could basically copy the entire thing here paste it in and now this should be a one and just to have a cleaner graph i want to convert these y values to integers and that is purely to make the x and y labels on our figure a bit cleaner we are nearly done all we have to do is run these two lines here again inside of the function let me put it in here and now every time we are submitting a new value i want to update my figure and i want to pass in the table content and with that let's run it now it's not crashing let me add a number in here one value isn't going to create a line but the second value is doing just that and now i can add more and more values they keep on extending the graph and what i can do now for example if you're confused about this one if i add a different letter let's say green we get a different color green in this case and if i add a star in here we get with a few more values something like this where we don't have lines we have stars for each value pair but r and dash seem to be the best options and all right with that we have our graphing app so this is basically all you need to connect map.lib to pi simple gui for the next part we are going to make an image editor and that one is going to look like this when we start the program we get a dialog to select a file and i have a test image here if i open this one we get to this window and in here we can set a blur we can set a contrast and we can flip the image let me remove the blur a bit and we can change the contour or emboss it and all of that is working pretty straightforwardly and of course all of this can be saved and let's save it as test two and that's pretty much it now before we can start coding this we need to install something because by default we can't really alter images but for that python has the pillow library and this is what we are going to install so either in the powershell or on the terminal type pip install pillow or pip3 install pillow but once we have that we can start with our code and here again i have the skeleton app and if i execute this we get the plain window that doesn't really do anything right now and as always let's start by creating the layout properly and this time we need a slightly more complex layout because we have two columns let me actually open the entire thing again to illustrate what we need later on and in here we have two main elements we have the control sliders on the left and we have an image on the right and this is a layout we cannot create in python bagooy by default so we need an extra element and essentially what i have done in here i have used columns this entire element here is one column and this element here is another column and that way we can place elements next to each other and i guess this is going to make more sense when we actually implement it but what i want to do is to create let's call it a control column and we also want to create an image column the image column is the easier one let's start with that one in here i just want to create a column and inside of this column we need a nested list and each nested list is going to be one row inside of this entire column you're going to see in a second how that works in more detail but for this one i only want a single element and that is sg image and in here we need an image path now later on we're going to get that image path from a pop-up but for now i just want to open test.png so we don't have to select the same thing every single time and this column we would now pass into this layout i want my image column and if i comment out the control panel and run this we get the image covering the entire window more or less but now what i can also do i can create a second column so sg column and in here we are going to get a more complex setup right now i have one list inside of this column and this is going to be the main container and inside of this main container let's do this over multiple lines i want to have individual rows and each row is going to be one list meaning the first list is going to be the first row and in here let's add sg button and let's just call it test and now what i can do in my layout i can add the control panel or the control column and run this and now we have two columns right next to each other now this we could have done with plain pie simple gui already we wouldn't need the columns for that but what we can do now is copy this entire row inside of the column and if i run this we have two rows on one side and then another column next to it and this way we are creating more complex layouts and i guess let's create the actual layout of the app and let's see how far we get for the actual layout i only want a single button and this one is save image and let's give them a key straight away so we don't have to do it later this one i want to call save but this is going to be the only button besides that i want checkboxes and those we haven't seen yet but you create them with a checkbox and then here you can give them a name let's start with flipx and then the key for this one should be flip x all in uppercase letters and if i run this we have a checkbox and essentially what this is going to return is a value that's either false or true if it's ticked that's just about it and this checkbox i want to copy and on the same row i want to get flip y and this one will have the key of flip y and now we have both of these elements right next to each other this is looking pretty good next up i want to duplicate this entire line because in here i want another checkbox and this one is called emboss and the key is emboss all uppercase and we want the other one i called contour and this one is going to get the contour key let's run this one now and we have a few more check boxes and now we need to create some sliders and those we also haven't seen yet but sliders are also really easily created you need sg slider and in here you have to determine a range and the range is the start and the end point we want a tuple and in my case i'm going to go from 0 to 10. let's try this one and we get a slider that goes from 0 to 10. obviously we want this one to be horizontal and that you also get quite easily all you need is the orientation and this one could either be h and this one would work or you could write horizontal in here and that would also work let's keep it at h so it's a bit more space efficient however there is one problem right now and that is that we don't have text for the slider a potential user wouldn't have any idea what to do with this and one thing that you could be doing is to add sg text next to it and call it i don't know slider doesn't really matter problem is this looks kind of ugly so i don't want to do that instead we are going to see another container element besides the column and this is called frame let me cut the entire slider out and what i want to do instead is create an sg frame element and this one needs two arguments it first of all needs a name let's call this one contrast and besides that it needs a layout and the layout again is a list with another list inside and in here we can insert the slider we just created and now if we run this we have a box around the element and we have some nice text at the top which is feeling significantly more professional and finally i can copy the entire line and the first item should be called blur and this slider remains the same and let's run this one now and there we go we have the entire layout i guess you could be adding a theme but do this in your own time i don't really mind so much although what i do mind is the sliders are also going to need a key because we are going to use those quite a bit and the first one i want to call blur the second one i want to call contrast and well with that we are pretty much done and let me minimize it so we have a bit more space to work with all right now we have to figure out how to use all of these elements to actually change the image and there are two steps we need to take here first of all we actually have to get the values from all of these elements and only once we have that we can use them to influence the image all that really means is i want to print all of the values and if i run this now we don't get anything because again we're not getting past this line here but that we can overcome by adding a time out and the timeout in my case is 50 milliseconds let's try this one now and there we go we have all of the values in real time what i can do now is change the blur change the contrast change emboss change contour and flip y and we always get the value updated in real time and this is what we are going to use for the actual image and i want to paste all of this inside of a function to keep the code a bit cleaner and let's call it update image and this one is going to get a couple of parameters first of all i want the original image the reason here is some of the image changes we are going to make are destructible meaning once we apply them we can't go back so we essentially want to keep the original and then modify this original and that way we can always go back and besides that we want the blur we want the contrast we want emboss we want contour we want flip x and we want flip y inside of the while loop i want to call this function and pass in all of my values the original we're going to leave for now we'll cover that in just a second but after that i want to get my values and in here i want blur and now let's copy this a couple of times the second value is the contrast then we have an argument for the emboss next up we have an argument for contour and all of this should probably be on multiple lines to make it easier to read what we want next is a value for flip x and finally we want a value for flip y and we should be having six values in total but now to finish this we are going to need the original and what i mean here by original is the original image in such a way that we can work with it and for that we are going to need the pillow library and this one you import with pil although in my case i only want to import specific things so what i want from pil for now is import image in here the original we want to get with image and we want to open an image and i guess we can do this quite smartly all the way at the top before we run anything else i want to create an image path and for now the image path is just going to be this test png and this image path we later gonna get from a pop-up but for now it's just gonna be that one path now we have an image if i run all of this we well we get an error because there's nothing in the function but if adam pass we don't see any difference but what we have now is an original image and i guess what we can do is to print the original and if i do that what we get is um well it's an image file that doesn't really tell us all that much but this is something we can work with and what we are going to do to this one is apply filters to it and filters we also get from pillow we just have to import them with image filter all we have to do is image and i want to get the original and then apply a filter and in here i need an image filter and now we have a couple of options the one for the blur is called gaussian blur and this one wants a number by how much we want to blur which in our case is what we get from the parameters so this blur here and now if i run this we get no difference the reason is that right now in our image editor we have two images this one is one image here and the other image is this original here and those two are different images they do not connect whatsoever right now and what we are doing up here is to influence this image basically what we have is internally we have a blurred image but we can't see it because what we actually show is a different image this one here which means we have to update our gui to show the image and for that we have to do a couple of things now obviously first of all we have to get our image element which i called image and we want to update this but now what we basically need is the image data and the image data we don't have right now and you couldn't just set image here if i tried this we would get an error that oh i just realized i made a mistake that right now the image element does not have a key which is not ideal so let's give it the key image and now let's try this again we're still getting an error that the int object is not callable which means that we couldn't just pass an image inside of the data here we have to do something else and what we have to do is to convert this image here to something python can use and for that to work we need another library or at least a part of a library and what i want to do is from io import bytes io and bytes io converts an image to something we can use in terms of bytes essentially all i want to do is get what is called bio and then get bytes.io and that is for now all we need and now what i can do i can get my image and save it with the bio information and now i have to specify a format which in my case is going to be png and once i have that i can get my bio and get underscore value and there should not be an underscore in between and with this line we have converted the image to something pisces per gui can use if i run this now i can use the blur filter and we have blur i guess one day i'm going to do a proper introduction to the pillow library and then i explain all of this in more detail but for now this is all we need so next up i want to apply the contrast filter and for that we want to update the image variable again and this time we don't want to get the original instead we want to get this image so this image here because we want to make sure once we have applied blur and we apply contrast as well that those two stack on top of each other and now all i want is to apply a filter and in here again i need my image filter and what i need now is called unsharp mask and this one again needs an argument that defines how much contrast we want and if i run this now our blur is still working but now we also have contrast this works just fine and next up i want to check if emboss is the case so if we have clicked on this checkbox here and if that is the case i want to get my image again and i want to filter it with image filter and this one is called emboss all in uppercase letters so let's run it now i can click on emboss and we get the embossed image works just fine and next up i can check if contour is the case and if that is the case i again want to apply a filter to my image we need image filter and in here we need contour also all in uppercase letters let's try this one i click on contour and this one is working also with the other filters as well and now finally i want to check if flip x and if flip y and for this one we need something else from pillow and this one is called image ops and this one we use again we want the image variable and now we want image ops and i want to apply a mirror and in here we have to pass in the image and let me copy all of this and to flip the thing in the y direction we need flip and with that we should have all of our options so i can blur it i can apply contrast there's ambos there's contour there's flip y there's flip x and that is pretty much it this is looking really good finally we are going to need the ability to save this image and this is let me minimize this function here this is going to happen first of all by us getting a path to the place we want to save the file and this i think could be a good challenge for you i want you guys to create a popup file to get the location and the file name where we want to save the file try to figure this one out yourself all i want first of all is to get the event and we call this one save and in here i want to create a save path or file path doesn't really matter and to get this path we need sg pop up underscore get underscore file and let's call this one save and save as should be true and besides that no window should also be true and if i print the save path now let me run this i can click on save image and here we already have the two images so let me save this one as another although there is one problem and that is that we don't have a file ending from this to fix that i want to add dot png and now that we have that all we really have to do is call image and save and then here we need our save path and we have to tell hello that this is going to be a png image the one final problem we have is that this image is only available inside of this update image to fix that we have to call global and image and with that let's try and we get an error that this should be a plus now let's try it we still have our owl and let me apply some blur and save the image test free and and if i look at the folder it's going to look like this and we have test three so we could indeed save the file let's do this a bit more obviously and let's apply a few more filters so i want to blur this a lot of contrast i want to contours maybe a bit less blur there we go and let's flip x and flip y and save the image as test free i want to overwrite this and now in the folder we have the formatted image looks absolutely horrible but it certainly is working the final thing that we are going to need is when we open the image we don't want to open the test.png we instead want to open a random file specified by the user this we get with sg pop up get file again in here i want to open something and no window should also be true and if i run this now we first of all get a dialog i want to pick my test image i want to open it and now i can make changes to it and i guess let's try another image test three the one we have already worked with and this one well we can make further changes to it but at the very least we know it's working cool so with that we have the entire image editor alrighty welcome back in this part we're going to create a music player it looks like this and then here you can click on play [Music] and then you have music playing you can stop as well and besides that you can also set the volume so in here i can go between 100 and 0. i guess let me play all of this and change the volume it's a fairly simple music player but i think it gets the basics across now before we can create this one we need pygm for the music and this we have to install first of all and that is going to happen either in the powershell or in the terminal all you have to do is either type pip install pi game for windows or or mac you are going to need pip 3 install pi game in my case i already installed it so i don't have to do it but if you don't have it you have to install it alright with that let's get started once again we have our basic python pegui setup if i execute what we have so far we get some very basic setup like this it doesn't do very much right now but it's a starting point now first of all i want to set a default style and this i want to do right at the start and the one i want to create is called sg theme and the name here is called reddit if i run this now you can't see much of a change but this is a fairly whitish theme now with that covered let's talk about the layout and the main thing we have to start here is we have tabs so if i show the app again there are a couple of things that we haven't seen yet most importantly we have tabs here we have play and we have volume besides that the other thing that is going to be new is we have a play and a pause button and both of these are image buttons which are kind of a pain to import but this is what we have to start working on but i guess let's get started by creating the two tabs inside of the layout we are going to need a new kind of element and this if i add a bit of white space here is called sg tab group and inside of this we have to create individual tabs those we create with sg.tab and each of these tab elements needs two arguments the first one is the name of the tab so for example the first one could be play and besides that we need a layout and these are going to be all of the elements that are inside of this tab which in my case i want to create a new variable that i call play lay out and this is going to be another list of lists that contain elements i'm going to create all of those in a second besides that i want to duplicate all of this and create another tab this one is called volume and in here we have the volume layout and with this we have some basic tabs although there's going to be one limitation although there is going to be a limitation and that is i have to put all of this into two levels of lists and this again is the kind of annoying thing about python per gui you need lists all the time basically what this tab group is expecting is a layout that looks kind of like the layout we always created where we have one list for the entire layout and then another list for each individual row inside of that layout and these are the same two lists we are creating here we are basically creating a whole new layout inside of the layout we already have i hope that makes sense all right now with that we have to create our play layout and we have to create our volume layout so let's get started and make sure you are doing all of this after the theme so the elements you create get the theming and let me start with the play layout and in here once more we need a list and this list has to contain other lists and for now just to get started let me just add a single word in here or well a single text to be more specific for the play layout i want sg text and then here let me just write song name doesn't really matter what it is for now we are going to change this anyway besides that i need another layout and this is going to be the volume layout in here again i need a list of lists and the main thing inside of the volume layout is going to be an sg slider and this one at the minimum is going to need one argument and that is the range and for this one we need a tuple with the min and the max value in my case the minimum value is zero the maximum value is 100 and with all of that let's run this and see what we get there we go we have tabs we have play and we have volume looks absolutely horrible for now but it's something we can work with and if you're following along you are probably going to struggle with all of the lists here so definitely go for this quite slowly it can be very confusing but now that we have all of that we can finish up the layout and there are quite a few elements we have to include so let's go through it step by step and let's get started with the volume layout because this one is quite simple now first of all i want to customize the slider and for that we have a couple of different attributes we can pass in here one argument is the default value and this is just going to be an integer which in my case is going to be 100. if i run this now and go to volume we are starting at 100 and this is going to be 100 of the volume besides that for the slider i do want to have an orientation and this one is going to be h short for horizontal and if i run this now we have a horizontal slider already looking much better finally i want to have a key and the key for this one is going to be let's call it volume although this is not going to have any kind of visible change so well don't really have to run it now finally there's one more thing that i do want to do and that is i want to have this slider always in the center of the tab and for that i need a couple more elements first of all i need s g b push before and after the slider and that way it's always in the vertical middle besides that i want to have s g dot push before and after the slider on the same row so let me copy it there we go and with these push elements this slider is always going to be in the center of the tab now right now this isn't going to be visible and i think i forgot a comma let's try this now there we go the problem is that this slider is already the largest element meaning it determines how big the tab group is going to be and because of that you can't really see the slider being pushed into the middle but once we have my element you will see what i mean so for now don't worry too much about it but we basically finished with the volume layout so i can minimize it and now we can start working on the play layout this one is getting quite a bit more complex because in here we actually see two more new elements let me run the finalized one again because i forgot one really important thing so here is the final app the two new elements we need are the image buttons and besides that we have this progress bar at the bottom now the progress bar is surprisingly easy but the buttons are kind of annoying because we have to import an image let's do it right now and then i can explain as we go along the buttons should be right below the text so i want to add another row in here and to create an image button you need s g dot button and for now so we can see something let's create simple text buttons that are called play and besides that i want to copy all of this and call this one pause if on all of this now we have play and pause although those are text buttons which i don't want as a consequence i want to get rid of the text here and i have to replace it for both buttons with an attribute called image data now the problem here is that we couldn't just import an image what both of these data attributes need is a base64 data string of the image and this we have to create by using a couple of different modules so let's go through it one by one first of all we have to import base 64. besides that we need from io import bytes io and finally we need from eil import image these two you should be familiar with from the image editor base64 is new it's basically a data thing that we need oh and i forgot in the beginning you also have to install pillow um sorry about that these three modules we need to import an image and convert the image to a base64 data string and this i want to do in a separate function because we have to do it twice let me create a new function and let's call it base64 image import and all we need in here is a path now first of all we have to import the image and this i want to store in the image this is going to be done with the pillow library all i need here is image.open and pass the path in here i guess while we are doing this let me just call base64 image import and inside of the folder besides the python file we have a pause and a play button image and then we have the music file and for now i just want to work with the play image and this is a png file so to import it all i need is a string with play dot png and for now let me comment out this line here with the buttons so we're not getting an error and now if i run this we are not getting an error that's a good sign but we can't see anything because inside of this function i'm not printing anything so what i want to do is to print the image now let's run this again and we can see we have a pillow image it doesn't tell us very much but it's a start now the image itself is completely irrelevant to us we have to convert it and this we need to do by creating a buffer so let me call it a buffer and this we get with bytes io and just calling it that's all you need the explanation here gets a bit more technical and it's not really what we need so i'm going to go over this a bit more quickly once we have this i want to save the image using the buffer and then i have to specify a format and the format in my case is going to be png with this we have an image available inside of our code and this image we now want to convert and this we do with the base64 module so we need base64 and then dot b 64 encode after that we need buffer and then get val u all of this i want to store in a separate variable and let me actually print it to show what we get so b64 let me run it and we are getting a really long string that doesn't make any sense although to our computer this is something that is really helpful all i want to do from the function is to return b 64. once we have all of that i can uncomment all of this and now for the image data i can call my base 64 image import and for the play button i want to have play dot eng and for the image data let me put it on a separate line because this is going to be very hard to read otherwise there we go i want to have the same function except now i want to have horse dot png and now if i run out of this we have the two buttons we still have to make some changes but at the very least it's a good start and well i do understand that this function here is really complicated and very technical and this is one of the slightly more annoying things in pisces in pagui importing an image is surprisingly difficult but well for our purposes we are done with this one so let me minimize it and never think about it again now besides that for both buttons i want to make two more changes the first one is i want to have a button color that is going to be white now if i run this the buttons already look better and besides that i want to have a border width of 0. that way we don't have a border and now if i run this we have the two buttons and this isn't looking bad at all and let me put the list ending here so this should make sense we have one row here we have another row with the buttons and finally we need one more main row and this is going to be the row with the progress bar and this we get with sg.pro res and by default this is going to need one argument the maximum length for now let's go with and now if i run this we have a very faint bar at the bottom it's really hard to see as a consequence let's change this by giving it a size and the size here let me go of 20 by 20. this is looking much better so for these numbers just play around to see what looks good we are nearly done the last thing i want to do is to add some proper spacing here because if i run out of this well you can already tell i want to have larger text and i want to have these elements here more in the middle of the entire music player which means i once again have to use a couple of v push and push elements all the way at the top i want to have a v push element this i want to duplicate and put it below the text and i want to duplicate it again and put it between the bottom row and the progress bar if i run out of this now we have a bit more spacing between the elements which i think looks much better besides that to get the text in the middle i want to use sg and push before and after the text element so let me duplicate it here we go now we have the song name in the middle and while we are here let me change the font of the music player to something like ariel 20 so it's a bit larger there we go this feels much better the same thing we now have to do to the buttons so for the buttons before the button i want to have sg push and after the final button i want to have another sg push that way i am getting an error because i forgot a comma now let's try this now we have the play and the pause button right in the middle what i found a tiny bit annoying here is that there was hardly any gap between the two buttons to fix that i did a tiny bit of a hack i guess you could call it what i did is between the two buttons i added sg text with an empty string and now if i run this once again i forgot the comma now if i run this we have a bit more spacing between the two buttons which i think looks better it's fairly subjective but alright with that we have the entire play layout the final thing that we need is we have to add some keys because i have to target the progress bar and both of the buttons and for that for the progress bar i want to have a key that i called row grass and for each of the buttons let me put it right here i have a key and for that let's call the play button play and the pause button pause let's try all of this to make sure i didn't make a mistake this is still feeling pretty good cool so with that we have our basic layout so i can minimize all of this and now we can actually start working on the functionality the very first thing that we are going to need here is a music file and this we are getting with an import so before we are doing any of this i want to create a file import let me add a bit of white space here and a comment with import song this we get by creating a path variable and i want to create sg pop up underscore get underscore file the same thing we have seen earlier in here we want to open a file and no underscore window should be true just in case you forgot let me print the path in terms of what we get and now if i run all of this the first thing we see is a file explorer and here we can see the folder i have all of my stuff in and the file i want to open is great boss which is a music file if i now click on open we have a path to this file and from this i am getting the name of the song in this case that is great boss although i have to clean this one up a tiny bit i have to get rid of all of this here and all of this so i only have great boss left this i want to do inside of a new variable let me call it song name and here i want to get my path and i want to split wherever we have a forward slash and from that i only want to get the last element and let me print the song name to see what we get and run all of this again now we get great boss.ogg now you could keep it like this but i do want to get rid of the ogg as well and for that i want to add another dot and split all of this again this time wherever we have a dot and now i want to have the first element or the one with the index zero with that i can run all of this again select great boss again and now we get great boss this is feeling much better and this song name i now want to use inside of the play layout or the song name there we go and now if i run this i can select great boss or any music file and now the name is going to be great boss cool so with that we have a song name problem is we don't have an actual song we just have a file path now for the actual song we are going to need pygame because python begui doesn't have music playing functionality in build that's actually kind of a rare thing in python in general very few modules can't play music it's a bit weird but in this case i want from pygame import mixer mixer is the pie game part that plays music and this we have to initiate so usually when you use pygame you have to run pygame.init for anything to work in this case we only want to initiate mixer so we want mixer.init if you are not running this mixer is not going to work this is a really important line and now that we have that i want to import the actual song and this we get with mixer dot sound and in here we need a path fortunately the path we already have it's this one up here so i can just copy it and paste it in here and i guess once we have done all of this let me print what we get so i can select great boss again and now we have a sound object at some point in memory which is really nice because this we can just play all we need is the song itself and then play if i run out of this again get my music and there we go we had some music although i don't want to play the song right when the program is starting so let me get rid of this for now and let me minimize the play layout as well so we have a bit more space to work with so now we do have a song we just have to figure out where to play it or rather when to play it and this is going to happen down here essentially i want to play the song when we are pressing the play button which we get inside of the play layout the button is called play which means in here i want to check if event is equal to play and if that is the case i want to get my song and play it and now let's try this again i want to import the same song and right now there shouldn't be any music but if i click on play we could hear some music i don't want to talk over the music because that makes me very difficult to hear but this is definitely working besides that i also want to have the ability to pause the music and this we get with if event is equal to pause i called this button and to pause music we need mixer dot pause unfortunately the song file itself doesn't have any pause functionality you have to target the entire mixer so if you play multiple music files they are all going to be paused but in our case that isn't really a problem so let's try once again i can select a file i can play it and i can also pause it the issue now is if i click on play again we are starting from the very beginning so let me try and you can see the problem that after i clicked on pause and play again we are starting from scratch which i don't want instead if the music is paused i want to resume it not play from the start and this we can also achieve quite easily because we can check if mixer dot get underscore busy don't forget to call it and this we want to check if it is false now this mixer dot get busy is a tiny bit weird you might assume from the name it checks if we are playing music or not and you wouldn't be wrong it basically does that the problem is once we started playing once this get busy is always going to be true which means if we haven't played yet this is really useful because if we haven't played anything we always want to start the song from scratch however if that is not the case we want to unpause the song meaning if we haven't played anything yet we always want to start the song from scratch but if we have already played something so else i just want to unpause the mixer which means i want mixer dot and pause and then we should just unpause the song like the method implies let's try all of this i can import the same file and now if i click on play we have music again and i can also stop it but now if i click on play again we are resuming and not starting from scratch again so this is working cool next up we can start working on the volume and this is actually very easy to implement it's going to work kind of like the sliders in the image editor so in my case i want to have the song and i want to set the volume and this is a pie game function in here for set volume we need a number between 0 and 1 with 1 being the full volume and 0 being the song being muted for this one i want to get all of my values and the values i want to target are the values from the volume slider so volume let's add the dashes as well so the volume slider is this slider here and inside of it we always target whatever value we currently have selected now for that to work there's one more thing that we do need and that is a time out inside of the read method let me set it to 1 this number should be very low and this is all we needed let's try this again now same file and let me play it if the volume is at zero you shouldn't hear any song but now if i increase it we should hear music again [Music] so alright with that we have our volume slider this one was actually really easy to implement finally the last thing we are going to need let me run all of this again i want to show the progress of the song in the progress bar down here now for that we need a separate timer because pygame has no functionality to check how far we are into the song which means we need another pie game module for time so all the way to top of the code besides mixer i also want to import time and time by itself also needs to be initiated although it's not an init method instead we have to create a clock and this we get with time dot lock if you don't have this clock object somewhere in your code pygame is not going to check the time so this is really important the code would still work even if you don't have it but time would always be zero so this is really important and besides that i need a couple more attributes or variables to be a bit more specific let me save them under a timer first of all i need the entire length of the song so song length and the length of the song i get with the song and this is this music file we have imported and now i want to get underscore length let me print what we get so song not song name i want to have song length let me run all of this again and we get the length of the song is 110 seconds point something now this point something is a bit annoying which means i want to convert all of this to an integer but the seconds i do want to keep because they are very easy to work with and before we continue this song length we already have to use because inside of the play layout or the progress bar right now this is always going to be a hundred but the maximum length of the progress bar should be the length of the song which means i want to pass my song length in here if i run out of this you are not going to see a difference because we are setting the length of this bar separately with this size attribute here but well trust me it works besides that for the timer we're going to need three different variables the first one is time since start and this one is going to be zero then we need a pause amount this one is also going to be 0 and then we need a playing variable this by default is going to be false and let me explain how this is going to work basically as soon as we're starting the song so let me add here this is the starting point which is going to be zero and from this point we are going to check the time of how long the song is played and that number we are storing inside of time since start and this is only going to be updated if playing is true however now we do have a problem because this logic always checks the time since the start which means we are always starting this timer from the point zero and this is a problem because we could pause the song for example we could play the song until here then we pause for a while then we play again then we pause again and then we play again in the current setup we are always checking this entire distance and this is what we are storing inside of time since start which isn't really accurate because we well skipped some huge sections and for that we have the pause amount and this one is increasing the number whenever playing is false and at the end for the progress bar we're going to subtract this amount from the time being played and the amount here is the sum of these two individual pauses and that way we always have the correct progress inside of the song now the logic here is a tiny bit annoying and you definitely have to think about it but well it is what it is it sounds much worse than it actually is let's actually implement it inside of the while loop before i am doing anything else i want to check if playing is true and if that is the case i want to update my time since start and the time i get with time dot get underscore ticks and this playing should be true as soon as we are pressing the play button which means inside of here playing should be true as soon as we press play and if we are pressing pause then playing should be false with that we are getting some numbers and these numbers still inside of the if statement for playing we can target our progress bar this we get with window and in here i want to have my progress bar i think i called it progress let me double check yes we are checking this progress bar here and this progress we want to update and in here we need a number now technically you could add time since start but that wouldn't really work because pygame checks the time in milliseconds and we want to have a number here in seconds that is very easily converted all we have to do is to divide the milliseconds by 1000 and then we get seconds and let me use floor divide so we're getting integers and with that we should already have something that we can't see so let's play all of this let me select the file and now you can see we have something although if you pay close attention there were a couple of problems first of all when i started to play the music we started somewhere here we didn't start all the way on the left on top of that if i play the music again we are making a huge skip and the reason is what i explained earlier basically let me move it to the side this time send start always starts from the beginning so when we are starting the program but between me playing the program and starting the song there was a time difference and this is why the progress bar started with a slight offset and by the same logic if we are pausing the song and playing again we are again starting from the beginning of the program and that way if we start again we get some weird numbers but this we can account for quite easily all we have to do when we get our timestamp start i want to subtract the pause amount the number we created here and every time we are pausing so either here or in here i want to increase the pause amount or more specifically once we start playing or unpausing again i want to add these numbers and this is going to be the same for both of these lines as a consequence right below playing i want to add my pause amount plus equal time dot get underscore ticks don't forget to call it minus time since start and this is going to give us the difference between the last pause and our current time and this is what we want to remove from our current progress i hope that makes sense the timer does get a bit confusing but with all of that we are basically done so let me run out of this again raid boss and now the timer starts all the way on the left and if i pause and wait a few seconds and start again [Music] we are progressing quite nicely so with that we have created a music player wasn't actually so bad i guess in here you do have a couple of fairly complicated things or slightly more complicated things the timer in particular is going to take you some time to get your head around so if you really want to understand it definitely have a look at this in your own time besides that the function to import images is well very annoying and possibly gooey but this is going to work for any kind of image so you don't really have to change it all that much if you want to adopt it to your own logic now before we finish this part i realized i made one mistake and that happened down here because set volume expects values between 0 and 1 but the values inside of volume are between 0 and 100 which means we have to divide all of this by 100 and that way we are getting a proper volume setup but with that we are done with all of this so now we have our music player for the next part we are going to create a weather app and this one is going to look like this we have a text field and in here we can type in any town or country let's say tokyo and we get the weather for tokyo it also works for entire countries let's say japan in this case and okay we get the same place but let's try another country usa we always get the capital of the country and the weather for the capital and let's try one more let's say paris and there we go this is working quite well and for this to work we are going to need one really important module and this one is called beautiful soup and what this module does is it scrapes the web which means it looks at a website and it takes information from that site and in our case we are going to use the google weather forecast to make all of this work but to get beautiful soup you need the powershell or the terminal and you have to type pip install beautiful soup 4 or pip 3 install beautiful soup 4. and with that let's have a look at the code and here once more i have the skeleton app that doesn't do anything right now well it does something but not very much for my layout i want something like this this here is my entire window and i want three major sections on the top we have the input element then on the left we have an image this could be a sun for example this is a horrible sun but you get the idea and then on the right side of that i want all of the weather information so here we have the name of the place we're looking at the temperature the current weather and the time i think as well doesn't really matter this is the overall setup i want to create and for that to work we need the column element again which i want to put in a separate variable let's call one the image column and sg and column and this i want to duplicate because in here i want to have an info column for the first row let me put this over multiple lines that's going to make things a bit easier to understand there we go for the first line i want sg input and i want an sg button and for the input here i want this to expand x and this should be true and let's give this one a key as well i guess input tends to work out quite well here and for the button i want something like enter or submit i guess enter works fine this would then be our first row and for the second row i want to have my image column and my info column and let's start with the info column that's going to be the longer one in here again we need a list that contains other lists and this one is going to contain quite a few different elements i guess the best way to work with this one is going to be to just copy the elements i want and paste them in here there we go we have three bits of text we have a text for the location the time and the temperature each of those have their own custom font and font size they all have a background color they all have the custom padding or these these and these then we have a text color and a justification and a visibility there's quite a lot of stuff in here and for the column things are going to be a touch easier because all i want to add in here is sg dot image and by default there's no image but i do want to give this one a key that is going to be image and i also want to give this one a background color that should just be plain white so ff ff and ff i think what i forgot is that this needs to be inside of another list let's try this one now and we can see that well we can't really see anything the reason for that is that all of these elements here are invisible so we have visible set to folds and i think that's a case for all of them right all of these elements are set to invisible so we can't see them and for the image we can't see it because we don't have an image yet that should also make sense and to make all of this work let's make all of this visible once we are pressing a button in my case this means if event is equal to i call this one enter and if that is the case i want to get my window and the first one is called location and let me copy this two times i also want to get my time and i want to get my temp and all of those i want to update and for now let's set visible to true that is important for all of them and besides that they all need to have some kind of string by default right now they have nothing and let's pass test in here just to see what we get and while we are here we can let me copy this one more time i want to set a random image so image i want to update and for the image there's something i haven't talked about yet and that is that inside of my folder we have another folder called symbols and then here we have various weather symbols and for now let's say i want to import snow looks quite good and to import that one i need a string then i want to go inside of the symbols folder and then here i want snow dot p and g and now if i run all of this and i click on enter now we have some sort of basic layout although doesn't look very good yet one way to improve all of this is to run sg.theme and the theme i want to go with is called reddit let's try this now this is already looking significantly better now let me click on enter and this is feeling much nicer the one customization thing i forgot was the enter button let's do this one right now this happens all the way up here and let's also set the border width to 0 and now we have a nice flat button if i click on this now we pretty much have the basic layout that we are going to need the other thing i forgot is that for the location text the font color should be white and this i have done for my time so i can just copy text color from here and pass it up here let's try now and enter and this is feeling much nicer so with that we have the basic layout now what we have to figure out is how to get the information from a website to make the actual weber information work we need two modules first of all i want from bs4 which is beautiful soup for import beautiful soup and since this is very annoying to type i am going to abbreviate this as bs and besides that we want to import requests to use them i want to keep all of this inside of one function let's call this one get weather data and in here i want to pass in a location the very first thing we need in here is a url so from what website do we want to get our information and let me explain how the system is going to work here i have a browser open and what i want to look for is let's say the weather in london and now google is going to give me some predictions and this is the information i want to get but now i need to figure out how i get to this url here without being able to type into the search bar and the trick essentially is that for this url this part always stays the same all that really changes is the location afterwards and then all of this stuff here we could just ignore we will get to the same website which means i could replace this london with something like let's say boston i will get to boston i could add usa and i would always have the right google search which means i want to copy this string here and return to my code and now the url is going to be the string we just got and then i want to add the location and this should be an f string just to make sure here what we could do is run the replace method that if we have any kind of space in this word we want to replace or well remove that space for example if we type new york this should be spelled in one word since for a url we can't have any kind of space in there how we are going to use this weather data is after we're pressing enter we run get weather data and we are passing in the values of the input field let me actually print the url just so we can see this is working and we are getting an error i have to change these single quotes to double quotes otherwise python is getting confused now let's try this there we go let's say i want to type in here berlin we haven't used yet if i press enter we get plus berlin with a space this shouldn't be in there and this space happens because there's a space here let's try it again now uh paris there we go we have paris and if i type in new york i keep on misspelling new york we get new york and this is then always the string we want to look for and looking for a website first of all means we have to create a session and this happens with requests dot session and this is basically what we tell the website when we are approaching it and now we need session dot address and here we have to define a string that says user agent and for this one we need one longer string let me copy it actually it looks like this it's basically telling the website we are approaching what kind of browser we are it's very technical information i would recommend to just copy this bit here and now we want to use that information to get an html document and that we get with sessions.get and we want to pass in the url and this is now what we can use with beautiful soup and what we have to do is to create what is called a soup and this we get with bs and in here i want to pass in html dot text and now what i want to do is called an html parser and let me explain what this means here is the website we have just seen but what our computer sees is something like this this is the html code of the website and all of these elements combined create all of this and what we have just done in the code and what we have just done in the code is to copy this entire text and paste it in our code which means now we have to figure out what elements we are looking for and that is what beautiful soup is for and in our case we want to get a name we want to get a time we want to get the weather and we want to get the temperature and these bits of information you get with soup dot find and in here we are looking for specific elements in web development they're called a diff it's basically a container and that container is going to have attributes which is shortened here to attrs and to attribute we are looking for is called an id and id in html is supposed to identify one specific element and the id we care about is called wob location and now i want to get the text from that bit and just to see if this is working let me comment out all the other things and let me print the name if i run this now i can type in london and if i click on enter we wait for a second and we get london uk if i click on we didn't use rome yet we get rome metropolitan city of rome italy and that is the information we are getting from the google weather forecast and now i have to do the same thing for the other variables as well and let me just copy this line here a couple of times because this is going to repeat a fair bit now for the time we need wb and dts or the weather we need wob dc and for the temperature we need tm and now once we have all of that i want to return the name the time the weather and the temperature i can close this function because we are done with it actually let me open it one more time because i want to get all of these variables get them returned from the function so now i have all i need to update all of these values here for the location instead of test i want to have the name for the time i want to have the time for the temperature i want to have the temperature the image we are going to cover in just a second and let's try this now and let's say one place we haven't used yet i guess brazil we can try do we get an error okay inside of here the problem i have is that the weather and the temperature are not inside of divs they are inside of a span document and i'm not going to explain web development but span elements are basically other types of container so this is why we get confused here let's try it now brazil again and now we get sao paulo and brazil we have 27 degrees and we have the current time although i do want to make some updates for the time i only care about the date not the actual time as a consequence what i want to do is to split the time we get and split it wherever there is a space and from the list i want to get the first entry which is the day of the week let's use one we haven't used yet let's say russia and now we only have the day of the week and for the temperature i want to show the temperature with a degree symbol and then the weather in brackets afterwards for that i have to turn this thing into an f string so let me put some brackets around it at the quotation marks and now to get the degree symbol we need a unicode character and that one looks like this and now if we try this let's say beijing and if i try this we get 8 degrees and besides that i also want to show the current weather in brackets this should be inside of the string like this and let's try now let's go with london and now we can see 11 degrees and cloudy this one is working really well what we have to figure out is the image and this is going to be a bit more extensive and essentially here we have a bit of a problem so let me copy how i got the image for one weather condition and this is the weather condition for sun it looks like this it just needs to be formatted properly and here we go the problem here is for the weather we have a ton of different options so google weather knows something like 40 different weather conditions and we have to account for literally all of them in my case if we have sun sunny clear clear with periodic clouds then i want to have the sun symbol besides that the other symbols i want to use let me just copy them in are going to look like this all we are looking for if the weather is in partly sunny mostly sunny all of the kind of sunny we get the part sun image if the weather is in rain chance of rain light rain showers and so on we have the rain symbol if weather isn't some kind of thunderstorm we get these if we have mist dust fog smoke all of these we have the fox symbol and if the weather is in any form of snow we get the snow image i hope this makes sense it's just very repetitive code there wasn't really a better way of doing this we just have to check for the different weather conditions that we get from google and i guess let's try this and what's a town we haven't looked for yet uh miami if i run this there we go we have sunny and that's one weather condition we could be having let's say what we get in iceland we get mostly cloudy also condition we have accounted for so all of this seems to be working just fine and i guess with that we are done with the weather app it wasn't actually that bad alright and with that we are doing the last program and that is going to be a face detector and this one is going to work like this here you can see me but more importantly you can see my face is being tracked so even if i move around the program knows where i am unless i move outside of the image and then it obviously doesn't know where i am anymore and more importantly at the bottom of the picture you can right now see people in picture one and this is well determined by the input so if there was another person in here this number would say two and well that's going to be the entire project it's going to be fairly straightforward and to make all of this work we are going to use the opencv library which is the python default for any kind of facial detection and this one you have to install so in the powershell or on the terminal you have to type pip install opencv python or pip3 install opencv python do not forget the dash python it is kind of important and with that out of the way let's have a look at our code and here one more time we have our skeleton app so this one doesn't really do anything right now and first of all we have to create a layout in my case i want to have two rows on the first row i want to just create an sg image there's no content for now but i do want to have a key which i'm going to call image and besides that i want to have sg and text and this one by default is going to say people in picture and let me spell this properly let's say we start with zero and this i also want to give a key let's call it text and i also want to justify this text and this one we are going to do with xband x and set it to true and justification should be c short for center and now if i run this we have some text we can't see the picture yet because well we don't have a picture and for that to work we need the opencv library and first of all we have to import it this happens with import cv2 and now we have to let me add another section let's call it get video we have to do two things in here first of all we have to get the actual video stream and this we get with cv2 dot video capture and in here make sure the v and the c need to be uppercase letters and this is now going to need one argument and in my case that is going to be a zero and what we are looking for here is the type of input we have in most cases that is going to be a webcam which is a zero in my case i have a dslr which works slightly differently so sometimes opencv decides the input source is a one i am not sure why that changes but play around with different numbers it should be some single digit integer like 0 1 2 3 something like that but now that we have that we are going to need something else and that is called a face cascade and for that one we have to import something and here we have the project folder opencv gui is the actual file we are working in right now and then we have a file called har cascade frontal face default and this is basically the data we need to make image recognition work and this one is designed for faces there are quite a few other data sets that work for something else like recognizing animals or bodies or specific parts of a face like the eyes if you want to look for different things you have to look for different files online obviously i guess really quick this here is the opencv github page and in here you can find lots more of these cascade files you have to go to data and in there you have haar cascades and this is also where i got mine from i am using this one here right now and this one is frontal face default there is also i3 glasses there's one for cat faces there's one for the full body there's the left eye there's the lower body there's lots of different things in here here we are back in the code and i want to cv2 dot cascade classifier and in here now we need the file name let me just copy it it's quite a long one and when you're doing this yourself make sure to not forget the dot xml but right with that we have all we need to get started what we now have to do in the while loop we have to first of all get our video and read it and this is going to return two values the first one we just don't care about the second one is going to return a frame so one image of our current video feed this video feature specifically and what we are going to do is set this frame as this image on every single frame of this while loop here and for that to work we first have to do some conversion and remember earlier when we did the image editor in there we couldn't just use the image we had to convert it to some byte format and this we have to do as well here but let me add another section and let's call it update the image in here we need something like image bytes and this opencv can do by itself so we don't have to import anything else we need cv2 and the command we need is imminent code and the format we want is p and g in fact it should be dot png and then we want the picture information which is our frame and this is going to return a couple of things but we only care about the one with the index one and that information we want to convert to bytes and now we have the information so all i have to do is get my image element and then update it with the data from image bytes and now if i run this we can see nothing the reason here once again is when we are running this entire while loop our program doesn't go past this line here for the simple reason that python begui is waiting for some kind of input which we don't have so we never get past this line we can fix that really easily all we need is a timeout named argument which in my case i want to set to zero and now if i run this you can see me hello there let me move the window to the center of the screen and you can kind of tell that the video is really choppy and this seems to be some kind of problem with the interaction between pyson bagooy and opencv opencv by itself doesn't do that sort of thing so if i close this even with a timeout of 0 here there seems to be some kind of delay anyway which is making our video choppy if you just use opencv this shouldn't be the case now we have a video how can we get facial recognition and for that first of all we need our image as a grayscale because that turns out to be really useful for image detection i have no idea why that is the case but what we want is our image in gray and this we get with cv2 and cvt color and we need two arguments in here first of all we want our frame and besides that we need the color information which in my case is cv2 dot color underscore bgr to gray and this is now going to convert our image to black and white which we can actually use so when i convert the image down here instead of my frame i could insert gray if i run this now you can see me again except now i am black and white but everything else still works just fine but this is information we don't actually want to show we just want to use it so i am going to stick with my frame but now the actual magic we get i want to store this in the variable faces and i want face underscore cascade which is the file we have created earlier by importing this image here which is what we are using now and what i want to do here is run detect multi scale and in here we need our grayscale image and then we need a few more named arguments and i think it's best to put all of this on separate lines so it's a bit easier to see and let me just copy them in that i think is going to be the best way i have a scale factor min neighbors and min size and basically what these different named arguments you do is to determine how our facial recognition is going to work so they set the parameters to what counts as a phase i suppose the easiest one to explain would be min size this one determines the minimum size of a face if i added a really large number in here we would only recognize a phase if it is really large on the picture which isn't very likely and these other factors work in kind of similar ways if you don't get a face or you get too many faces then play around with these numbers and just see what you get now this is the face we actually need what i can do now is let me print faces let's run all of this again you can see me again and now in the bottom left you can see a list with one entry and this is the position of my face i guess the position and the width of my face if i move around you can see the numbers change in different ways and if i move outside of the window let me go all the way here now we have an empty list and if i come back in there are coordinates again and if there was more than one person this faces list would contain more than one list inside of it which means we can use the length of this list to determine how many people are inside of the window and let's do this all the way at the end let's call it update the text and in here i want to get my window the text and i want to update this one and let me copy the text from the top and i do want this to be an f string and now i need the information here for the amount of people and this could be a good challenge for you try to figure out from the faces list how many people are inside of the picture this one should be really easy we want our faces and from that we want the length meaning if there is one item inside of this list we have one person inside of the picture and now if i run this you can see in the bottom people in picture one and if i go outside of the picture it is going to be zero i suppose an easier way of doing this is to cover my face there you go it's working pretty good with that we are very nearly done the last thing i want to do is to draw the rectangles and how this one is going to work let me print the faces again and now if i run this again you can see me again and now in the bottom left we have four numbers the first one is x the second one is y and then we have the width and the height of my face or whatever opencv considers my face to be and these are numbers we can use to draw a rectangle but first of all we want to cycle through the list inside of faces and the most efficient way of doing this is for the tuple x y w and h in phases and what we want to do with that information is cv2 and draw a rectangle and in here we need four bits of information we need the image we want to draw on we need the top left the bottom right and we need a color oh and i forgot we need a line width but the line width is super easy let's just go with two doesn't really matter for the image we want to have the frame now we have to figure out the top left and the bottom right and this is going to be very similar compared to what we have done with the snake video so i guess this could also be a good challenge for you try to use these values here to figure out the top left and bottom right of the image i suppose the best way to understand this is if i draw all of this here is our entire video feed this video here and my face is here and the points we want to find is a point here and besides that this point here which is the bottom right and the upper point is the top left and the top left is the really easy one because all we need here is x and y those points we literally already know so this point is already covered the question now is how can we get to this point down here and the answer for that isn't that much more difficult pretty much all we have to do is go from our top left point and either move to the weft or down by the height of this rectangle and if we combine these two arrows we get the one arrow pointing to the bottom right and all that means in practice my top left is just going to be x and y and my bottom right is going to be i guess it's an x and y position as well but for the x position here i want my x for the top left plus the width and then for the y position i want the y position of my top left plus h and now we just have to set a color and for that one opencv wants a tuple with an rgb color value which means we need r g and b short for red green and blue in my case i went with zero amount of red zero amount of blue and the full amount of green which is 255 which is going to give us a green rectangle if i run this now you can see me again but now i have the green rectangle around my face that keeps on following me really really well okay not perfectly well if i rotate my head sometimes it loses it by a tiny bit but it's mostly going quite well cool and with that we have finished the entire tutorial series that took forever to make so i hope you enjoyed it and i'll see you around
Info
Channel: Clear Code
Views: 212,328
Rating: undefined out of 5
Keywords:
Id: kQ8DGP9p2LY
Channel Id: undefined
Length: 264min 43sec (15883 seconds)
Published: Sun Jul 24 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.