How to Make a GUI Calculator with Tkinter

Опубликовал Admin
13-08-2019, 13:00
Updated: August 12, 2019 Creating a text-based calculator is a common exercise for beginners. But when you already have intermediate programming knowledge, you may want your calculator to have a GUI, as most software does. This wikiHow shows you how to write a calculator that has a GUI with the Tkinter library in Python 3.


  1. Open a text editor or IDE. If you don't prefer a specific program, it's easiest to use IDLE, an IDE that is usually installed together with Python.
  2. Import Tkinter. It is usually installed together with Python, so you don't have to install anything new. Write the following line at the beginning of your program:
  3. Save and run the program to test that Tkinter is installed correctly. If it works, you won't see anything, the program will just import Tkinter and exit. If it doesn't work (i. e. some error message appears), the next steps also won't work until you fix the problem.
  4. Define a Window subclass of the Frame class. This subclass will define what the calculator window will look like. For now, just include the basic code that initializes a window:
  5. Make the window show up. You have already defined what a window looks like, but you also need to actually create a window.
    • Call the Tk() function to initialize Tkinter and and return an object that will let you control the main window.
    • Create a window of the Window class that is attached to that object.
    • Set a caption for the window.
    • Show the window and react to events.
  6. Add a text field. This is where you'll display the calculation and its result. The first function in the following code creates a text box that has white background, black text and is 1 line high. The second function actually inserts the text, which is "0". This code belongs into the __init__() function of the Window class.
  7. Place the text field in the grid. The grid will position your widgets, like the text field and the buttons. Since the grid should be at the top, place it in row 0. Since it's across the entire row, which will be 4 columns wide, it's not necessary to specify a column number, but you need to specify that it spans across 4 columns.
  8. Create and align the number and operation buttons. The callback function for every button will be self.notice with what is written on the button as argument. Since you can't use functions with arguments directly as callback function, you'll have to put it into a lambda instruction. For now, define that function to pass (do nothing) or to print that value.
  9. Save and run the file to test whether the buttons are aligned correctly. If not, adjust the position. While the buttons, window and field can look differently on different systems, it should approximately look like this:
  10. Write the self.notice function. You already defined it so that displaying the button works, but the code doesn't do what it's supposed to do yet. Instead of printing the value, it should display it on the result field to show the user that the calculator noticed their input. Usually, the program can just append the value, but if the only thing present in the calculation field is the number 0, that 0 should be removed and replaced by the value.
    • The "0.0" that is present in the get() and delete() functions indicates the beginning of the textbox text. It follows the format "lineNumber.columnNumber", which is used for indexing textbox text.
  11. Add buttons to calculate and clear. Right now, it's only possible to enter numbers and operations. But a calculator should actually calculate the result of what the user enters. When that calculation is finished, it should be possible to clear the output and calculate something else. To do these things, add two more buttons in row 5. To visually set them off from the others, make them span across 2 columns. Set self.displayRes and self.clear as the callback functions.
  12. Define the clear() function. It should delete all text in the textbox and replace it with a 0.
  13. Define a function to display the result of the calculation. The actual calculation function will be quite complex, and it would be even more complex if it also had to get the input from the text box and write the output into it. This is why you should define another function for this.
  14. Define the calculation function. This is the most complex function of the entire program. Make it recursive, i. e. calling itself with other arguments. This allows it to reduce the expression to simpler expressions until it's only a number, then perform the specified operation with the number and the other number, then use that result in the not-so-simple expression, and so on.
    • Don't proceed if the input is "ERROR". That string will be used to indicate that a calculation failed. Since it's not possible to continue calculating with a failed result, the function should just return "ERROR" itself.
    • Check whether the input is a single number. If it is, return that number, since there's nothing left to calculate. Note that the following expression will raise a ValueError if the input isn't a single number. The actual calculation and recursion happens when such an error occurs. try: return(float(task)) except ValueError:
    • Check whether there are brackets. If so, calculate the result of the expression inside the brackets separately from the other things. If not, proceed to check other operations. if ")" in task: level = 0 maxLevelStartIndex = 0 maxLevelEndIndex = 0 for i in range(0, len(task)): if task[i] == "(": level += 1 maxLevelStartIndex = i if task[i] == ")": level -= 1 if level != 0: print("ERROR: brackets don't match: %i layers too much in expression %s" %(level, task)) return "ERROR" for i in range(maxLevelStartIndex, len(task)): if task[i] == ")": maxLevelEndIndex = i break newTask = task[:maxLevelStartIndex] + str(self.calculate(task[maxLevelStartIndex+1:maxLevelEndIndex])) + task[maxLevelEndIndex+1:] return self.calculate(newTask)
    • Other operations (add, subtract, multiply, divide) are arranged by priority. The program splits by the + or - first and calculates the two parts, only then by the * or / . Note that it catches the error that happens when you try to divide by 0, and returns "ERROR" if that happens. If there is no error, it returns the result. elif "+" in task: tesk = task.split("+") res = self.calculate(tesk[0]) for t in tesk[1:]: res += self.calculate(t) return res elif "-" in task: tesk = task.split("-") res = self.calculate(tesk[0]) for t in tesk[1:]: res -= self.calculate(t) return res elif "*" in task: tesk = task.split("*") res = self.calculate(tesk[0]) for t in tesk[1:]: res *= self.calculate(t) return res elif "/" in task: tesk = task.split("/") res = self.calculate(tesk[0]) for t in tesk[1:]: try: res /= self.calculate(t) except ZeroDivisionerror: print("ERROR: division by 0") return "ERROR" return res
    • If the input could not be converted to a number not because it's an expression, but for another reason, that returns an error. This is necessary because the Tkinter text field allows the user to enter input on the keyboard. If the user enters a letter, that should return an error, and this code makes sure it does. print("ERROR: invalid expression") return "ERROR"
  15. Make graphical error messages. Right now, if an error happens, it displays "ERROR" on the result text field and prints the error to the terminal or IDE from which you started Python. But a good GUI should also display the errors graphically. This is done with the messagebox.showerror function. It takes the message heading as first argument and message text as second. You can use "Error" as message heading and the message that was previously printed as message. For example, replace with messagebox.showerror("Error", "ERROR: division by 0")
  16. Check your code. Your entire code should look like this now. This are 120 lines totally, and 116 lines not counting the comments.
  17. Save and run the code. It's finished. Now test it and/or enjoy your own calculator. It should look approximately like in this screenshot:
Users of Guests are not allowed to comment this publication.