How can I program a calculator with a GUI using tkinter in Python?
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
Jaydreamer
Updated on June 29, 2020Comments
-
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 about 10 yearsWhy 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.