DEV Community

Discussion on: Building An OOP Calculator And What It Means To Write A Widget Library

Collapse
 
itr13 profile image
Mikael Klages

I made a version based on your code, where I tried to decrease duplicate code, and increase extendability.

The biggest change was putting all the buttons in a 2D list, and rather base the grid position based on that. This makes it easier to move buttons around and add new ones, as you don't have to calculate their grid-position, or update the position of other buttons. It also makes it less prone to mistakes.

The second biggest change was making all the buttons use a single method, which meant I could get rid of a lot of duplicate code, where the only difference was the "command" parameter. I also made it have an optional parameter for width to allow for the "equals button" to use the system too.

Other than that it works exactly the same as your program (other than having equals set self.string with the return value rather than an empty string)

from tkinter import *

BUTTON_WIDTH = 4


def b_info(symbol, operation=None, width=1):
    if operation is None:
        operation = lambda s: s+symbol
    return (symbol, operation, width)


class Calculator:
    def __init__(self, parent, x, y):
        self.button_font = ('Verdana', 15)
        self.entry_font = ('Verdana', 20)
        self.parent = parent

        self.button_height = 1
        self.container = Frame(self.parent)
        self.container.grid(row=x, column=y)

        self.string = ''

        self.entry(0, 0)

        numbers = [
            [b_info(str(i)) for i in range(n, n+3)]
            for n in range(7, 0, -3)
        ]
        buttons = [
            [ b_info('+'), b_info('-') ],
            [ b_info('*'), b_info('/') ],
            [ b_info('('), b_info(')') ],
            [ 
                b_info('0'), 
                b_info('=', lambda s: str(eval(s)), 2),
                b_info('clear', lambda s: ''),
                b_info('<', lambda s: s[:-1])
            ], 
            []
        ]
        buttons = [i+j for i,j in zip(numbers+[[]], buttons)]

        for row, y in zip(buttons, range(1, len(buttons)+2)):
            x = 0 if y > 0 else 2
            for b in row:
                self.button(b[0], b[1], x, y, b[2])
                x += b[2]


    def entry(self, x, y):
        self.entry = Text(
            self.container, font=self.entry_font, state=DISABLED,
            height=self.button_height//2, width=BUTTON_WIDTH * 5)
        self.entry.grid(row=x, column=y, columnspan=5, sticky='we')

    def button(self, char, operation, x, y, w):
        print(x, y)
        def execute():
            self.string = operation(self.string)
            self.display(self.string)

        button = Button(
            self.container, text=char, width=BUTTON_WIDTH,
            height=self.button_height, font=self.entry_font,
            command=execute
        )
        button.grid(row=y, column=x, sticky='we', columnspan=w)

    def display(self, text_):
        self.entry.config(state=NORMAL)
        self.entry.delete('1.0', END)
        self.entry.insert('1.0', text_)
        self.entry.config(state=DISABLED)

class App:
    def __init__(self, master):
        self.master = master
        calc = Calculator(self.master, 0, 0)


root = Tk()
app = App(root)
root.title('dev.to calculator')
root.mainloop()
Collapse
 
abdurrahmaanj profile image
Abdur-Rahmaan Janhangeer

thank you very much. yes, the two main improvements are legitimate ones, easier positioning and a general purpose button function. indeed, a novel view of the affair. just some bits of comments appreciated.

i'll refine and build something on those. else, are you interested in a widget lib collab?

Collapse
 
alialdaw profile image
alialdaw

sorry but iam a begginer in python and i love your kind of code i want more explanation for this code please

Collapse
 
itr13 profile image
Mikael Klages

I'm a bit full on projects at the moment, but if you have a git repo or something I can check it out when I have time.

Thread Thread
 
abdurrahmaanj profile image
Abdur-Rahmaan Janhangeer • Edited

that's the way!

edit: kind of pet project