Calculator with GUI Using Python Tkinter (Less Than 200 lines of Code)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome back to this series on python project-based learning for beginners i'm soyuz from programmers and in this video i'll teach you to create your own calculator app in less than 200 lines of python code so let's get started before we get started with the tutorial let me first show you what our final calculator app is going to look like for this video we will try to mimic the built-in standard windows calculator app so i'll open this file so here we have the digits to add buttons from 0 to 9 and also a button to add the decimal point then we have the buttons to perform the four basic arithmetic operations along with square and square root okay so let me use our calculator to find the product of 23 and 17 so i'll say 23 into 17 and press equals to and as you can see we get 391 as the answer also notice that we have a label that keeps track of the entire expression so if i want i can even add the square of 15 to this answer so i'll say plus 15 and now i'll use the square button to find its square i'll press equals to and we get the expected value by the way we can also use our calculator with the keyboard so first i clear these values using the clear button and now i'll use the keys to type the expression like 27 times 6 plus 5 minus 3 times 7 i'll press enter and as you can see our calculator follows the correct order of operations to give us the right answer now let's learn to build this calculator app using python and tkinder before we get started with the tutorial i want to mention that we're going to use an object oriented style of programming to build this calculator so make sure that you're familiar with object oriented programming first you can check our python object oriented playlist to brush up on your oop skills the link will be in the video description remember that the main takeaway from this video should not be just to build a calculator in python but also to learn things that are often overlooked like how to structure your project and write clean readable python code so let's start writing our code i'll first create a new folder in my workspace i'll call it calculator then i'll open this folder with pycharm it's always a good practice to create a new virtual environment for each of our python projects this will help us manage dependencies for each project in a separate and isolated environment so let me open the terminal and create a new virtual environment using the v and v module i will say python hyphen m v and v and then the name of our virtual environment i'll also call it v and v so i'll say v e and v i'll press enter now let's activate this virtual environment i'll say dot slash vnv says scripts slash activate for now we are going to use only the built in tkinter module so we don't have to install any dependencies yet now let's create a file to write all of our python code so i'll create a new file and i'll call it calc.pi so i'll say calc dot pi now let's start by importing the built-in tk enter module i'll say import tk enter as tk then i'll create a calculator class that will contain all the components and functionality of our calculator so i'll say class calculator now i'll create an init method for the calculator class where i will do all the initializations so i'll say def underscore underscore init underscore underscore self and inside this init method i'll first create the main window of our calculator app using the tk class of the tkinder module so i'll say self dot window equals to tk dot dk then i'll specify the width and height of this window so i'll say self dot window dot geometry and i'll specify the size as 375 times 667 this size is also the standard logical resolution for iphone 8. now i'll also disable resizing for this window i'll say self dot window dot resizable and i'll pass 0 comma 0 then i'll also give our app a name in the title bar so i'll say self dot window dot title i'll give it the name calculator also calculator now let me create another method called run to start our calculator app so i'll say def run and then i'll say self dot window dot mean loop then outside this class i'll say come outside this class and i'll say if underscore underscore name underscore underscore equals to main inside this if statement i create an object of the calculated class called calc so i'll say calc equals to calculator then i'll run the run method of the calculator object source calc dot run these lines of code will run only when calculate pi is run as a script from the terminal so let me save this file and run it and you can see that our main window was created with specified dimensions and we also have calculator in the title bar now we're going to create two frames one for the display and the other for the buttons so i'll say self dot display frame equals to self dot create display frame and then self dot buttons frame equals to self dot create buttons frame now let's define these two methods first i'll define create display frame so i'll say def create display frame inside this method i'll say frame equals to tk dot frame since we are creating this frame inside our main window i'm going to specify self.window i'll also specify the height for this frame so i'll give it a height of 221 let's also give this frame a different background color so i'll first define a variable called light gray so i'll come here and i'll say light gray and give it a hex value of f5 f5 f5 then i'll come here i'll specify bg the background color as light grey now let's back this frame to our main window so i'll say frame dot pack and i will specify expand equals to true and fill equals to both these arguments will allow our frame to expand and fill any empty space around it finally let me just return this frame so i'll say return frame now let's do the same for the buttons frame so i'll say def create buttons frame inside this method i'll create a frame so i'll say frame equals to tk dot frame and i'll pass self.window and similar to the display frame i'll also pack this frame so i'll say frame dot pack i'll say expand equals true and fill equals to both then and also return this frame so i'll say return frame now that we've created the frames let's add display labels to our calculator as we saw in our demo the calculator app will have two different labels one to display the current expression and the other to display the total expression so first i'll define both the current expression and the total expression so i'll come here and i'll define self dot total expression i'll set it to zero i'll do the same for self.current expression so i'll say self dot current expression and i'll set it to zero then i'll create a method called create display labels to create these labels so i'll create the display label so i'll say def create display labels and inside this method i'll first define the total label so i'll say total label equals to tk dot label and i'll add it to self.display frames as itself dot display frame i'd also specify the text for this label so i'll say comma text equals to the value of the total expression so as itself.total expression i will also use anger equals to tk dot e this will help position the text at the east side of the frame i'll also change the background and foreground colors for this label so first i'll define another constant i'll call it label color so i'll say label color and i'll give it the hex value 2 5 2 6 5 e then i'll come back here and i'll specify bg as light gray and fg the foreground color as the hex value of the label color so as a label color i'll also give it a padding in the horizontal direction so i'll say pad x equals 24 let me also change the font style for this label so first i'll create another constant so i'll come here and i'll create another constant i'll name it small font style and i'll give it a tuple value of arial and 16. now i'll come back here and i'll specify font equals to small font change it to comma finally i'll pack this label with expand equals to true and fill custom so i'll say total label dot pack expand equals to true and fill equals to both for the current label i'll just copy and paste this line so i'll say the same thing and now i'll change total label to label i'll change self total expression to self.current expression i'll also change total label here to label then i'll come here and i'll define another constant so i'll say large font style and i'll give it the value arial comma 40 and also bold now i'll come back here and i'll specify the font now as large one style finally i'll return total label and label so i'll say return total label comma label now i'll come back to the init method and here i'll say self dot total label such itself total label comma self dot label equals to self dot create display labels now i'll save this file and i'll run it and as you can see our display labels have been added let's now add the buttons to our calculator we'll use the grid system to add all the buttons so first let me create a dictionary of all the digits and the corresponding positions so i'll come to the init method and i'll define self dot digits as a dictionary in a standard calculator the digits start from seven so first i'll add seven as the key with the value one comma one we will later use this value to specify that seven should be placed in a cell with row one and column one similarly eight should be placed in root one and column two so i'll say it and give it the value 1 comma 2. now i'll copy paste other values we also have 0 at the center of the last column so i'll add 0 and i'll give it the value 4 comma 2 let's also add a decimal point button at position 4 comma 1 so i'll say dot i'll give it the value 4 comma 1. now i create a method called create digit buttons so i'll come here and i'll say def create digit buttons and inside this method i loop through our dictionary and add each button to our button stream so first i'll say for digit comma grid value in self.digits.items and for each of the digits and grid values i'll create a button so i'll say button equals to tk dot button and now i'll place it inside self read buttons frame so i'll say self dot buttons frame i'll also specify the button text as digit so i'll say text equals to digit but since it's an integer value i'll also convert it to string before passing it so i'll say string of digit let's also give a button a background color and a foreground color so first i'll define white i'll say white equals to x value fff and now i come here and i'll specify bg the background color as white and fg the foreground color as label color then to place these buttons in a grid i'll say button dot grid and i'll pass row as the first element of grid value which is grid value 0 and column as the second value of the grid value which is grid value one i will also specify sticky equals to tk dot north south east west so that our buttons stick to every side and fills up the entire grid cell i will now call this method from inside init so i'll say self dot create digit buttons now let me save this file and run it and you can see that our buttons have been added they look very small at the moment so let's change that i'll first define the digits font style so i'll say digit font style and i'll give it the value arial 24 and bold now i'll come here and i'll specify the font as this is font style i will also remove the border from this button so i'll say border width equals zero now let me save this file and run it again and we can see that a new font style has been added to the buttons also the border has been removed a button still don't fit the entire window but we'll fix that once we add all the buttons so now let's add the basic arithmetic operator buttons for this i'll first create a dictionary called self.operation so i'll come here and i'll say self dot operations and i'll paste this value this dictionary maps the arithmetic operation in python to the operator symbols here these two values are unicode values that represent the division symbol and the multiplication symbol now i'll create a new method called create operator buttons so i'll go here and i'll create a new method so i'll say def create operator buttons and inside this method i'll loop over the previous dictionary so i'll say for operator operator and symbol in self.operations.items i will define button sdk dot button i'll add this button inside self dot buttons frame so i'll say self dot buttons frame and i'll specify the button text as the symbol let me now define two more constants so i'll come here and i'll specify the default font style so as a default font style and i'll give it the value arial and 20. i'll also specify another color so i'll come here and i'll specify another color called off-white and i'll give it the hex value f8 fa ff so that's f8 fe ff now i'll come back here and i'll specify bg the background color as off-white and i'll specify fg the foreground color as label color so i'll say label color i'll also specify font equals to default font style i'll also remove the border from these buttons so i'll say border width equals zero now let's place this button to the buttons frame grid so i'll say button dot grid we know that the operator button should be at the last column and start one row above the digit buttons so i'll first define a counter variable called i outside this loop so that's i equals 0 and now i'll say row equals to i i'll specify the column as 4 and also specify sticky as tk dot north south east west finally i'll increase the value of i by 1 so i'll say i plus equals 1. i will now call this method from inside the edit method so i'll come here i'll specify self dot create operator buttons let me save this file and run it and as you can see the operator buttons have been added similarly i'll create the clear button and the equals to button so i'll define a new method called create clear button so i'll come here and i'll say def create clear button and inside this method i'll first copy this code and i'll paste it here then i will change symbol to c for clear i will also change the grid values we know that the clear button will be at the top most row so i'll first replace i with 0 and also replace 4 with 1. for now i'll also add column span equals to 3 so that this clear button will span across 3 columns so i'll say column span equals to 3. now listen now let's define the create equals button for this i'll just copy this method and i'll paste it here i will change create clear button to create equals button i will change c to equals to sign now i'll define another color so i'll come here and i'll specify light blue as the hex value cc edff now i'll come back here and i'll specify the background color as light blue since our equals button will be at the last row and span across two columns i'll specify the row as 4. the column should be 3 and it should span across 2 columns so i'll say 2. now let's call these methods from the init method so first i'll come here and i'll define a new method so i'll say create special buttons and inside this method i'll call self dot create clear button and self dot create equals button then i'll call the create special buttons from the init method source itself but create special buttons now i'll save this file and i'll run the code and we can see that the buttons have been added as specified now let's expand this button so that they fill the entire space so i'll come to the init method and here i'll create a for loop that loops from one to four so i'll say for x in range one comma five and inside this for loop i'll say self dot buttons frame dot row configure and i'll pass in the value x and i'll also specify weight equals to 1 then i'll copy this line instead of row configure i'll say column configure these lines of code will help our rows and columns to expand since we specified a non-zero weight our buttons can now grow to fill the empty spaces by the way we also have the zeroth row so let's add this row configure for the zeroth row as well so i'll come here and i'll specify zero and finally let me finally save this file and run it and you can see that our buttons finally occupied all the empty spaces we will add the square and square root buttons later in our program now that we have added all the essential buttons let's start adding functionality to these buttons by the way if you're finding these videos useful a sub to the channel would be much appreciated before moving to the next section of the video i want to mention that the programming team has created an app that allows you to run python from your phone this app contains bit size lessons that are easy to understand a built-in python interpreter so that you can run python on your phone quizzes and many more the app is available on both ios and android links are in the video description let's start by making the digit buttons functional first i'll create the methods that will update the total label and the current label so i'll come here and i'll create two methods first i'll say def update total label so let's say update total label inside this method i'll update the text property of cell.total label so i'll say self dot total label dot config and now i'll change the value of text to whatever the value of self the total expression is so as itself total expression then i'll do the same for the current label so i'll say define update label so i'll say update label i'll change self dot total label change the text property to cell dot current expression now let me create a method called add to expression that will add a given value to the current expression so i will come here and here i'll specify a new method so i'll say def add to expression this method will take in a value and what i will do inside this method is i'll append this value to work on expression so i'll say self dot current expression plus equals to and then the string of our value now finally i'll update this current expression so i'll say self dot update label now let's add the functionality of this method to our buttons so i'll come here and i'll specify the command so i'll say comma command and i'll say self dot add to expression and i'll give it the valid digit but since the command has to be a function i'll wrap our method using the lambda keywords also lambda then i will remove the initial values of self.total expression as self.current expression so i'll make them empty strings let me save this file and run the code and now i'll press the buttons okay so currently a decimal point gets added to the current expression for any digit button we press let's see why that is so i'll come to the create digit buttons okay so it's because our lambda function uses the digit variable which gets reassigned every time in the loop due to this all the buttons give the last value of digit which happens to be the decimal point to fix this problem i'll create a parameter called x and i'll bind it to the digit in each iteration of x so i'll say x equals to digit and here instead of digit i'll say x now let me run this code again and our digit button finally work now let's add functionality to our operator buttons the operator button should append the symbol to the end of the current expression append it to the total expression and finally clear the current expression for the next entry i will implement the method called append operator and you'll exactly understand what i mean so i'll come here and here i'll create a new method so i'll say def append operator this will take in an operator and inside this method i'll first append the given operator to the current expression so i'll say self dot current expression plus equals to the operator then i'll append the current expression to the total expression so i'll say self dot total expression total expression plus equals to self dot current expression finally i'll clear the current expression for the next entry so i'll say self dot current expression equals to an empty string finally i'll update both the total label and the current table so i'll say self dot update total label and self dot update label now i'll add this method to operator buttons so come here and similar to before i'll say command equals to lambda which will take in a value x and i'll bind it to the operator variable in each iteration and then i'll say self dot append operator and i'll pass in x let's save this file and run it now i'll press 9 plus and as you can see the plus operator is first appended to the current expression then we appended the current expression to the total expression and finally we'll clear the current expression for the next entry let's now add functionality to the clear button and the equals to button in a similar way so first i'll come here and i'll specify the clear method and what this method will do is simply clear both the current expression and the total expression so i'll say self dot current expression equals to an empty string i will do the same for the total expression so the total expression this will also be an empty string now i'll update both of the labels as itself dot update total label okay so i then update total label as well so i'll say update total label now i'll come here i'll specify command equals to self.clear next let's review the eval function before implementing the functionality of the equals to button the eval function evaluates and returns the value of a valid python expression let me show you what i mean so first i'll go to the python console tab in pycharm and here i'll say eval 2 times 3 plus 3 i'll make it a string i'll press enter and you can see that this expression gets evaluated and the final result is returned we are going to use this eval function to evaluate our total expression when the user presses the equals to button so now i'll close this tab i'll come back to my correlator and i'll define the evaluate method here so i'll say def evaluate inside this method i will first append the current expression to the total expression such as self dot total expression plus equals to self dot current expression then i'll update the total label so i'll say self dot update total label then i will say self dot current expression equals to eval of self dot total expression i'll also wrap this function with the string function so that a string is written at the end now i'll reset the total expression so i'll say self dot total expression equals to an empty string finally i'll update the current label so i'll say self dot update label now i'll come here and i'll say command oops i'll say command equals to self dot evaluate let me finally save this file and run it and now our calculator app should be fully functional i'll try to find the product of 8 and 9 so i'll say 8 times 9 equals 2 and we can see that it gives us the correct answer we can also reset the expressions using the clear button so if i press the clear button these expressions are now removed now that our calculator is fully functioning let's enhance some of its features first of all let's add the square and square it buttons to the calculator also when we currently type an expression like 9 times 9 we can see that the actual operator symbol is not displayed let's replace this python operator symbols with the actual operator symbols next if we try to do calculations like 1 divided by 3 we can see that the values currently overflow the window width so let's truncate our results also if we try to divide by 0 so i'll say 1 divided by 0 so here we get an error message let's try to put our eval function in a try block finally we'll also make our calculator app usable from the keyboard first let's start by adding square and square root buttons to our calculator so i'll first come here and i'll remove the column span parameter for the clear button to make room for square and square root buttons and then i'll copy paste this code to create the square button first of all i'll change the name to create square button so create square button then i'll change the text to x slash u 0 0 b2 this unicode value represents the square symbol i will also change the command to self.square now let's define the square method so i'll say def square and what this function will do is i'll say self dot current expression equals to eval and i'll evaluate the string which is the self dot current expression and i'll just square it so i'll just do square and finally i'll wrap this using the str method and i'll update the label so i'll say self dot update label by the way i also have to change this column to 2 so that it appears next to the clear button similarly for the square root button i'll copy paste both the square button and the square method so i'll copy paste this code i'll change square to s qrt and instead of 2 i'll say 0.5 i'll also change the value of the name of this method so i'll say create qrt button i'll also change the text to slash u 2 2 1 a this unicode value represents the square root symbol and then i'll type x and now i'll change the column to three let's add these buttons inside the self.create special buttons so i'll come here and i'll add this method here so i'll say self dot create square button and i'll say self dot create square root button so i'll say create squared button now i'll save this file and i'll run the code and as you can see these buttons have been added then i'll try to find the square of 3 so i said 3 square which is 9 and then i'll again find the square root oops we forgot to actually add so i'll come here i'll change the square to square root so now if you run this thing again we try to find the three square then find its under root we get the actual output to change the operator symbols i'll go inside the object total label method and i'll simply replace the python operators with the actual operator symbols so first i'll say expression equals to self dot total expression and now i'll loop through all the operators from the operations dictionary so i'll say for operator comma symbol in self dot operations dot items i'll simply replace these values so i'll say expression equals to expression dot replace and now i'll replace the operator with the symbol so i'll also add white space around it so i'll say f and i'll say symbol now i'll change the self.total expression to this expression let's save this file and run it let me type an expression like 9 times 9 now you can see that the operator symbols have been displayed for truncating the result i'll go to the update label method and use the slicing operator to limit its length to 11. so i'll add 11 at the end now i'll save this file and run the code and now if i say 1 divided by 3 equals 2 and we can see that our result no longer overflows the screen to handle exceptions i'll come to the evaluate method and i'll put the eval function inside the try block i'll come here and i'll say try now i indent this code if an exception occurs i'll set the current expression to error i'll come here and i'll say accept exception oops exception as e here i'll just say self dot current expression equals to error and inside the final block i'll say finally i'll put self dot update label now i'll save this file and run the code and now if i do something like 1 divided by 0 i'll press equals 2 we get error at this point our calculator is working correctly however it doesn't take inputs from the keyboard let's change that to make our calendar usable from the keyboard we need to bind the keys of our keyboard to the respective methods from our calculator class so first i'll create a method called bind keys so come here and i'll say def bind keys and inside this method i will say self dot window so self dot window dot bind and firstly i'll bind the enter key so i'll say return here i'll pass the function lambda it takes in an event and i'll execute self dot evaluate this line of code specifies that pressing the enter key is the same as pressing the equals to button now i'll do the same for the digit buttons and the operator buttons so first i'll loop through all the digits so i'll say for key in self dot digits i'll say self dot window dot bind and pass in key and for the function i'll say lambda which is two parameters the first is the event and the second is the digit i'll bind the digit to the key and i'll return self dot add to expression digit similarly for the operator buttons look through all the operators so i'll say for key in self dot operators self dot window dot bind key and for the function i'll again define a lambda function so i'll say lambda that takes in two parameters the first is the event and the second is the operator i'll bind the operator to the key and i'll say self dot append operator and pass operator now i'll call this method from the edit method so i'll come here and i'll say self dot bind keys i save this file and run the code now i'll use the keys of my keyboard to type 9 times 8 i'll press enter and our calculator works as expected now that we have made our calculator fully functional let's create an exe file from our calculator pi file this will allow us to run the calculator app from any windows device without any python setup for this i'll use pi installer pi installer is a tool that allows us to convert a python application into a standalone executable let's first install the pi installer from pip so i'll see so i'll go to the terminal and i'll say pip install pi installer now that the pi installer is done installing i'll use it to convert calc dot pi to an executable file so i'll see pi installer installer and i'll say hyphen iphone one file iphone w and then the name of our script i'll say calc dot pi this one file flag specifies that our executable should be created as a single file and this w flag specifies that python should not bring up the terminal while running the calculator gui so i'll press enter so now i'll go to my workspace and we can see that the build and disk folders are created by pi installer let's open the disk folder and we can see that we have a calc.exe file let's open this file we can see that our calculator app is running from here as well i hope you found this project helpful i encourage you to try and add more buttons and modify this calculator as you please that's it for this video you can find all the links i mentioned in the video description if you want more of these videos let us know in the comments and if you like this video hit that like button subscribe to the channel and i'll see you in the next one happy programming you
Info
Channel: Programiz
Views: 27,294
Rating: undefined out of 5
Keywords: Build your own Windows Calculator Clone (200 lines of Python) | Python Projects for Beginners, Python Projects for Beginners, Python project-based learning, project-based learning, project-based video, Python Projects, calculators, real-world problems, Windows Calculator App, Tkinter, Python, programiz, programiz python for beginners, project beginner tutorial, programiz project, calculator, build calculator, python calculator, python projects
Id: QZPv1y2znZo
Channel Id: undefined
Length: 43min 45sec (2625 seconds)
Published: Wed May 05 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.