Introduction to GUIs in Python with PyQt5

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello in this tutorial I will show you how to create a calculator with Python and PI QT 5 it's going to end up looking like this and will function like any basic calculator and the steps I will be going through happen at these times if you look for specific things as always if you want to use pi QT you need to install pi QT because it doesn't come along with PI even by default so I've earned the power shell on the terminal type pip install PI QT 5 and you should see the installation animation and if you can import PI QT 5 in the Python script without getting an error message you are ready to go let's establish the basics now before starting this project let's talk about gooeys our graphical user interfaces all that means is that when you use your computer you click on icons and buttons instead of typing text while python is a powerful language that can be used from exploring planets to running service to analyzing data very little of that needs a graphical user interface and as a consequence Pythian doesn't really have tools to display graphical elements like buttons or sliders for that we need additional libraries they are quite a few available for that you can find all of them in the Python documentation the default one is called TK inter which is short for TK interface and while this one is installed along with Pavin it is not a core part of the language in fact CK inter is not even made in Python but in the language called tcl/tk another important library is the Qt framework which was originally developed for C++ but it can be used in Python i've-i've-i've pie QT or of Pi site there's a bit of history why they are two modules for the same purpose but the two are really similar so it isn't something you need to worry about all that much and finally there's Kivi which is based on OpenGL this one is particularly good if you want to make a mobile app of Python which library you choose depends on quite a few factors and each has advantages and limitations I will use PI QT for this tutorial because it is nice and simple but with a little bit of tinkering you could create the same up with the other libraries as well and before I get into the logic of pie cutie I have to warn you that you need to have at least a basic understanding of object-oriented programming in Python otherwise nothing is going to make sense specifically you will need to know how to create an object from a class how to use self an inheritance of super but you won't need multiple inheritance or decorators at least for this tutorial and besides that you should also know about lambda functions with that out of the way let's talk about her pie cutie works essentially every pie cutie program is built on two objects one is called cue application the other is main window the one you will work the most with is the main window object because this one handles the graphical elements and the logic of the application itself cue application does all the stuff that happens under the hood like event handling and initializing the modules most of that is automatic though so you don't actually have to vary all that much about this part once those two are created you have a basic framework that you can add visual elements to and in PI Q T these are called widgets which it could be a button or a field it could also be a container that holds other elements for the purpose of this tutorial we all need some basic ones I will use one called cue push button which is a very simple button and perfect for a number and operator keys then I will use the widget called cue line edit which can be used to input and display text in the calculator this one is going to show the results and finally I will use Q widget which is basically just an empty container which is perfect to create structures on the application and that is everything we need to get started let's jump into the code with that first we need some imports we don't actually import all of pie cutie instead I will only import pie cutie 5 thought cutie widgets and I call it qtw I took the naming convention from Alan Moore's book mastering GUI programming in Python which is an excellent book that I would recommend if you want to learn more about pie cutie cutie widgets holds all the widgets and is enough since we are only going to make a simple app without much styling and with the import out of the way let's create the class that holds all the elements that will be shown to the user for that I will need to create a class that I would call main window and that inherits from cute ewq widget then I add dunder init and within that I was a called dunder init on the clouds we can heard from with super and after that I called self-control let me go through this and explain we start by creating a class in the usual way and this class will inherit from qwidget the main window class itself is what will hold all the visual elements and whatever it inherits from will be the base all the other elements will be placed upon in this case qwidget is just an empty container so we start with a completely empty window and next I initialize the attributes of the class we've done there in it and for now this will be empty except for the inheritance from the apparent class which is needed to make it function properly and after that they are self taught show which displays all the elements of the object created from the main window class right now it wouldn't show anything except an empty window because we haven't added any widget yet that will happen a little bit after the main window class I need the line AB equals Q jwq application and I pass in an empty list you could pass in more here for additional functionality but I just don't need it and well that creates the queue application that keeps track of all the stuff under the hood the two things left to do are to create an actual object from the class I call it MW and assign it a class main window and with that we have the two objects that maintain our application the one thing left to do is to add app dot X underscore which tells Python to run the application and the underscore is important to avoid some naming conflicts with Python and that is it if I run the code now you should be able to see an empty window it can be resized and closed but that is about it so let's add the graphical elements next to add a widget to the window all we need is to attach it to the class so effectively the attributes of the main window become the graphical elements for a really simple example how this works let's add a title in the init function of main window I add self dot set window title and insert a string calculator if I run the code now we get a title for the window and a similar pattern is used to add all the buttons and labels but there's one step in between and that is the layout you see the title can only go in one place so it doesn't need a layout but if I added a button peyote wouldn't know where to place it so it wouldn't show it at all instead the structure we need is this we have an empty container right now to that one I will add a layout and on this layout I will add the button and the labels there are a couple of different layout Styles some of the big ones are QV box layout and qh box layout the V and the age stands for vertical and horizontal respectively if I add one of these the widgets will be placed in a vertical or horizontal arrangement which wouldn't be used before a calculator instead I will mostly rely on what is called a cue grid layout which gives us a two dimensional grid that elements can be placed on the layout that I will be using for this project is going to look like this on the window I create a cue box layout that one will hold a container and inside of that container I had a cue grid layout and in this grid all the calculator elements will be placed now you might be asking why I don't just put a grid inside of the main window and that is a very good question basically it is just done to keep the code a bit more readable and lean I will come back to this one in a little bit so in the code I had self dot set layout and insert QT wqv box layout now we have a layout for the main window but we can't see it because it's just a layout let me just add a single button to illustrate I will add a variable bTW and one and assign a QT w r cube push button and it sort of strength test if I run the code now we can see that we can't see anything except that the window has become very small when we launch it to make the button visible we need to attach it to the layout first so in the code I had self-taught layout or add widget and into that I passed PT and one if I run the code now we can see the button we also get the little animation when we press it but nothing much happens yet that part will come in a little bit and just to reiterate what happened first I created a layout on the main window of QV box layout then I created a button widget called BTN one on the next line and this button was added to a layout of the main window and that is the basic way how to add widgets to the same window and it doesn't matter what widget you want to add they are all added in the same way so you could add a button or a text field or you could add a container that itself contains other elements that last part is what I will do actually essentially I will create another function and then that function all the buttons and labels will be generated and still within the function they will all be added inside of a container widget and then only this container will be added to the main window so back in the code I delete the two lines for the simple button and create a function inside of the class and call it keypad and insert self on the first line of keypad I add the variable container and assign a QT w dot Q widget this is going to be what holds all the other elements and on this container I set the layout to be a grid layout with container that said layout and I insert QT w the view grid layout and with that we created an empty container with grid layout that is part of the same object as the empty container with the vertical layout now I only need to create and add all the widgets to the first container and touch that one to the second one so let's add all the widgets now the widgets I want are the following I want the line that displays all the output then two buttons with result and clear and then the buttons from 0 to 9 and obviously the operator keys and all of that is going to involve quite a bit of typing because every single element needs to be added manually I already inserted all of the buttons so you don't have to watch me type for too long I started with the liner displays the text and put it in a variable called result under schofield and assign it QT w dot Q line edit without any arguments next I added the two buttons for entering and deleting the numbers both are just plain buttons and then I created the ten buttons with the numbers from zero to nine each of them is stored in their own variable and finally I needed the keys for the operators so button for plus minus multiplication and division and with that we have created the widgets but now we need to add them to the layout to achieve that let me explain how queue grid layout works essentially this kind of layout creates a grid automatically for you and that grid grows depending on how large it needs to be its top left field has the coordinates 0 and 0 and you just need to add fields by specifying the row and the column and as soon as you place an element the grid grows large enough to incorporate it and by default each element takes in one cell of the grid but you can specify elements to span over a number of cells and that covers the basics so in the code you still need add widget' and insert five arguments the first is to widget you want to place the second is the row and the third is to column and those are the arguments you absolutely need the final two are to specify how many cells the widget should occupy so the fourth element is for the number of rows or tags and the final one how many columns it occupies and with that one out of the way we get to even more typing because we need to add every single element we created earlier to this layout again I prepared this one to save some time so on Rosi row I have the result field that spends 4 columns so takes up the whole space of this row on row 1 I have the result in the Clear button that each take two columns from Row two to Row 4 I always added three buttons followed by an operator button and on Row 5 I added the button for 0 that spends 3 columns and is followed by the final operator and to finish things off I just need to add self-taught layout or add widget' and insert container which adds the container with the buttons to the actual main window and all of that happens inside of a single method that is neat and tidy and that was the reason why it didn't just add the grid layouts straight to the main window and if I run the code now we can see all the buttons they don't do anything just yet and the styling is boring but it is a start although before I go to the next section I will change one small thing and that is to itself before the result field both when I create and also when I place it this is to attach the result field to the object itself and make it accessible from outside of the method essentially all of the buttons only exist inside of the keypad and method for now and we can't access them from the outside of this method and if that sounds super weird have a look at some of the tutorials on object oriented programming without that pie cutie is really inaccessible right now the styling is fairly bland though and if you scale the window things get even worse and sadly both styling and scaling at topics that easily require their own tutorial so I won't cover it in this video but we can do one quick thing to improve things a little bit there are default styles that we can apply the one way of right now is pretty ugly and the better one is called fusion to apply that one I need to go to the end of the code just before the execution and type a dot set style and insert qtw that style factory dot create and insert a string fusion here this tells the queue application to apply a certain style when it gets the widgets from the main window so if I run the code now things are looking a little bit better still not great and the scaling is weird as well but it's something let's make the calculator do stuff now right now you can type into the text field and click on the button but there's no reason to do that because they have no functionality and to add that I need to cover two important concepts signals and slots it's actually pretty simple every widget can emit a signal after a certain event so if a button is pressed it sends a signal to another widget and that widget ideally has a slot to receive that signal and that's the theory of how widgets communicate the only signal I will use is called clicked which is emitted when a button is pressed and every single button will be able to send that one I will also only have a single slot and that is for the text field to change its text depending on what button is pressed for a simple example here's the result button if I wanted to emit a signal when pressed I will need to emit an argument called clicked and what I assigned needs to be a function and to be clear here I assigned a function itself I do not call it so no brackets after it for simple things we could either create a function without parameters or use a lambda in case it didn't come across a lambda it is basically a one-time-use function without a name and it gets executed whenever you create it it's a really useful concept check it out if you've never seen it before but what if you wanted to execute a function with a parameter well you would just need to put the function with the arguments inside of a lambda function I will make use of that quite a bit actually let's do a simple example first before I jump into the logic of the calculator say I want to display the text test when I click on the result button so on that button I had clicked equals lambda and to target the result field and itself dot result field but set text and inserted text I want here so out a string test if I execute the code now and press the Enter button we can see the text test but obviously we need more sophisticated logic so I will need a few more methods and also insert arguments into them and that is why the result field got the self so and other methods can access it let's talk about the logic needed for the calculator it is a little bit more complex I start with a method on the number keys so whenever one is pressed Methodist's triggered with an argument I call it numb press for example when I press the button for numb press is cold with a four pass into it and I will have another method for the operators that have a called func press and insert the operator as an argument so it's fairly similar to the buttons that way I get the signals with the appropriate information in them my next problem is that I want to displayed in numbers as the buttons are pressed and get the resolved when the enter button is pressed let's work on the first problem the numbers appear in the result field when pressing the buttons and that they are properly separated when you press an operator key to achieve that I will create two lists one is called temp underscore nums and the other fin underscore numbs and the logic is going to evolve around these two in the simplest case only numbers are pressed and the operator keys haven't been touched in that case when a number key is pressed the associated number is stored in the temp num list as a string and when I press multiple buttons in sequence that sequence of numbers will be stored in that list all as a string so if I pressed 4 2 and 0 I would have a list with the strings 4 2 and 0 why are you strings will become clear in just a little bit but this step is finished by just joining all the elements together as a string and passing this as text into the result field so that covers just pressing the buttons now to the operators once an operator is pressed another method is called in that one all the values in the temp num list are joined together and the resulting string is stored in the fin num list and the fin num list also gets the operator that was clicked on the pendant as well to keep of the earlier example before 2 & 0 will become 420 and if I press plus the fin num list would have the strings 420 and plus also pressing any operator empties to temp num list and this function also changes the result field text to display the joined elements of the fin num list now we have a problem though after I pressed an operator I can see a number plus the operator but if I pressed another number I can only see a number that can be fixed by changing the method for pressing a button I just need to add an if statement that if there is something in the finem list displayed that before the content from the temp num list add if thin num is empty just as paid attempt number Ariel and with that logic we have the text display covered now we just need to do the calculation part and the main thing we have to figure out is how to make Python do the calculation we stored in the list luckily there's a function for that it's called eval and it evaluates a string so if I have a calculation inside of a string it gives me the result so when the enter button is pressed I turn all the content of the thin num list and whatever is left in the temp novelist into one big string evaluated and then at an equal sign and a result to the string and all of that gets displayed in the result field and the last thing now is to add a function for clearing if you made a typing mistake so the clear just erases whatever is in both lists and set the text in the result field to an empty string and that is the entire logic you need for a calculator let's implement all of this in the code now I start by adding a to list in the init method of the class so right after calling super both are empty for now next up we are back to some typing for every single button I need to add a signal again I type this part are ready to save some time both the result and the Clear button have their own method since neither has the parameter I just pass in the method without calling it then I have the number button they all have the same method but different arguments so I have lambda and insert a method with the argument here and the same logic applies to the operator buttons except that they have a different method now we just need to define those four methods and things are nearly done I start with num underscore press and the parameters are self and key number first I add the number from the button to the temp numbers list then I create a local variable of a called temp underscore string and assign it a joint string of the temp num list and if something exists inside of the finem list I want to print that as a string and if it doesn't then I just want to print a temp number list as a string to the result field and that finishes the num press method already now to the operators this one is called func under sculpt press and it takes himself and the operator as parameters in this function I had all the temp dump elements into a string and appended to the fin num list along with the operator that was pressed and then I emptied a temp number list and such a resolved field to whatever is in the kingdom list as a string obviously and to calculate the result field I work on the func underscore result method this one only takes self as the parameter it first takes in all the elements from both lists and turns it into one long string I will pass it into a variable of a called thin underscore string and then I create a variable I would call result underscore screen this one will get the result of the previous string so evolve thin string and on the next two lines add an equal sign and the result of the original string and then I display the result in the result field and to finish bangs all that is left is to work out the clear color method it only takes self its parameter and all that it does is to empty both lists and set the result field empty with the clear method and that is it if I run the code now I have a working calculator sadly it's really buggy if I had an empty field and press Enter the calculator would crash also if the last element in the string is an operator we also get a crash but these are mostly minor problems if you got this far I'm sure you can fix this yourself and it's true that it looks a little bit boring and that it's also quite buggy but you know the first step to being good at something is to be bad at something so if you work on the calculator and check out Alan Moore's book you can vastly improve it but that's it I hope you enjoyed this tutorial let me know in the comments if you have any question otherwise for next week I will show you how to make a fancy graph about the decline of the Simpsons I will see you then
Info
Channel: Clear Code
Views: 57,500
Rating: 4.8315506 out of 5
Keywords: Python, python tutorial, PyQt5, PyQt5 tutorial, PyQt5 gui, pyqt python, Pyqt app, python gui, gui, python programming, graphical user interface, introduction to python gui
Id: 8jrEVihl-E4
Channel Id: undefined
Length: 26min 10sec (1570 seconds)
Published: Tue Dec 03 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.