How can I program a calculator with a GUI using tkinter in Python?

41,904

So, I'll explain the code you've given as best I understand it. The class Calc() contains all the functions for this piece of code. The structure means the main GUI (set up later) can access each function easily. Within the Calc() class, you have your functions (denoted by def etc.). These contain the various methods by which this code computes it's output.

Outside of the class, we have the Tkinter UI code. This code builds your window inside of which your various buttons and displays sit. The positioning of the buttons and text fields in this case is governed by the 'grid' method. As you can see, every time the code sets up an object (here only Frame, Button and Entry objects), there is an associated .grid(row=x, column=y...etc). This specifies the relative positions of each object in the UI. For example, using the grid method you could stack two objects by giving the first object row=1, column=0 and the second row=2, column=0 etc.

The for loop:

for j in range(1,4):
    for k in range(3):
        bttn.append(Button(calc, text = numbers[i]))
        bttn[i].grid(row = j, column = k, pady = 5)
        bttn[i]["command"] = lambda x = numbers[i]: sum1.num_press(x)
        i += 1 

is probably the only part of the UI that is not straightforward to see if you're just starting out. In essence all it is doing is building buttons automatically (saving you the time to code each one individually). The first two lines in the loop are (hopefully) obviously looping over values in specified ranges. Beneath that the line bttn.append(... creates a button object in the calc frame set up earlier calc = Frame(root), with the button text being given by the list of numbers (literally numbers="789456123" above). Initially, i = 0, so numbers[i] would return the first element in the list numbers, numbers[i] for i=1 (the next time it loops over) would give 8 and so on. The bttn.grid(row = j, column = k, pady = 5) uses the grid positioning method mentioned earlier, but here the j and k are given by the values in the loop itself (values between 1 and 4 in the case of rows, and values between 0 and 2 - 3 columns - in the case of columns). If you run the code, you can see that this will position all the keypad buttons for inputting numbers. The last line in this loop (besides i+=1, i.e add 1 to i), handles assigning the button a command. The command will call an associated function, in this case the numpress function in Calc(). As you may be able to see, numpress itself updates your display with whatever number you press.

The final block of code in this example handles the remaining operations for the calculator, and you will notice that each also follows the above pattern of creating a button, assigning a command and positioning the button in the UI. With what I've explained above, you may be able to see that each of the remaining functions in Calc() governs an arithmetical operation, or clear etc.

I realise this is a wall of text, but I hope it helps! If I've been unclear or there is anything in particular you don't understand, let me know, I'll try and explain it (I've not long learnt myself!).

You might find this Tkinter UI Guide useful, I learnt a lot of the basics from that guide.

Good Luck

Share:
41,904
Jaydreamer
Author by

Jaydreamer

Updated on June 29, 2020

Comments

  • Jaydreamer
    Jaydreamer almost 4 years

    I'm taking computing for GCSE and one of the tasks for our controlled assessment is to create a calculator with a GUI.

    I'm able to program a simple calculator without a GUI but I don't understand exactly how it can be done with a GUI.

    Below is a code that I got from teampython.wordpress.com, which I vaguely understand but it would be very helpful if someone could explain each individual step to me.

     # calc.py - a Python calculator
     from tkinter import *
    
    
    class Calc():
        def __init__(self):
            self.total = 0
            self.current = ""
            self.new_num = True
            self.op_pending = False
            self.op = ""
            self.eq = False
    
    
        def num_press(self, num):
            self.eq = False
            temp = text_box.get()
            temp2 = str(num)      
            if self.new_num:
                self.current = temp2
                self.new_num = False
            else:
                if temp2 == '.':
                    if temp2 in temp:
                        return
                self.current = temp + temp2
            self.display(self.current)
    
        def calc_total(self):
            self.eq = True
            self.current = float(self.current)
            if self.op_pending == True:
                self.do_sum()
            else:
                self.total = float(text_box.get())
    
        def display(self, value):
            text_box.delete(0, END)
            text_box.insert(0, value)
    
        def do_sum(self):
            if self.op == "add":
                self.total += self.current
            if self.op == "minus":
                self.total -= self.current
            if self.op == "times":
                self.total *= self.current
            if self.op == "divide":
                self.total /= self.current
            self.new_num = True
            self.op_pending = False
            self.display(self.total)
    
        def operation(self, op): 
            self.current = float(self.current)
            if self.op_pending:
                self.do_sum()
            elif not self.eq:
                self.total = self.current
            self.new_num = True
            self.op_pending = True
            self.op = op
            self.eq = False
    
        def cancel(self):
            self.eq = False
            self.current = "0"
            self.display(0)
            self.new_num = True
    
        def all_cancel(self):
            self.cancel()
            self.total = 0
    
        def sign(self):
            self.eq = False
            self.current = -(float(text_box.get()))
            self.display(self.current)
    
    sum1 = Calc()
    root = Tk()
    calc = Frame(root)
    calc.grid()
    
    root.title("Calculator")
    text_box = Entry(calc, justify=RIGHT)
    text_box.grid(row = 0, column = 0, columnspan = 3, pady = 5)
    text_box.insert(0, "0")
    
    numbers = "789456123"
    i = 0
    bttn = []
    for j in range(1,4):
        for k in range(3):
            bttn.append(Button(calc, text = numbers[i]))
            bttn[i].grid(row = j, column = k, pady = 5)
            bttn[i]["command"] = lambda x = numbers[i]: sum1.num_press(x)
            i += 1
    
    bttn_0 = Button(calc, text = "0")
    bttn_0["command"] = lambda: sum1.num_press(0)
    bttn_0.grid(row = 4, column = 1, pady = 5)
    
    bttn_div = Button(calc, text = chr(247))
    bttn_div["command"] = lambda: sum1.operation("divide")
    bttn_div.grid(row = 1, column = 3, pady = 5)
    
    bttn_mult = Button(calc, text = "x")
    bttn_mult["command"] = lambda: sum1.operation("times")
    bttn_mult.grid(row = 2, column = 3, pady = 5)
    
    minus = Button(calc, text = "-")
    minus["command"] = lambda: sum1.operation("minus")
    minus.grid(row = 3, column = 3, pady = 5)
    
    point = Button(calc, text = ".")
    point["command"] = lambda: sum1.num_press(".")
    point.grid(row = 4, column = 0, pady = 5)
    
    add = Button(calc, text = "+")
    add["command"] = lambda: sum1.operation("add")
    add.grid(row = 4, column = 3, pady = 5)
    
    neg= Button(calc, text = "+/-")
    neg["command"] = sum1.sign
    neg.grid(row = 5, column = 0, pady = 5)
    
    clear = Button(calc, text = "C")
    clear["command"] = sum1.cancel
    clear.grid(row = 5, column = 1, pady = 5)
    
    all_clear = Button(calc, text = "AC")
    all_clear["command"] = sum1.all_cancel
    all_clear.grid(row = 5, column = 2, pady = 5)
    
    equals = Button(calc, text = "=")
    equals["command"] = sum1.calc_total
    equals.grid(row = 5, column = 3, pady = 5)
    
    root.mainloop()
    
  • Russell Smith
    Russell Smith about 10 years
    Why go with PyQt? For a beginner who is learning GUI programming, what is wrong with tkinter? It is a fantastic GUI toolkit for learning, plus it is probably already installed. I have nothing against PyQt, but if you're going to give advice, at least explain why you suggest going with something different. Without an explanation, the advice is useless.