GUI Калькулятор на Python tkinter

Статьи

Введение

В ходе статьи напишем GUI калькулятор на языке программирования Python с использованием модуля tkinter.

Написание GUI калькулятора

Для начала импортируем библиотеку tkinter:

from tkinter import *

Создадим объект класса Tk(), укажем разрешение окна 268×288, заголовок «Калькулятор» и запретим возможность изменять разрешение окна:

from tkinter import *

root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

root.mainloop()

Создадим виджет Frame() и отобразим его методом grid():

from tkinter import *

root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

root.mainloop()

Добавим текстовое поле (виджет Entry()) на фрейм, укажем шрифт Arial 15 размера жирного начертания, толщину 24 и запретим возможность писать в нём. Отобразим его методом pack():

from tkinter import *

root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

input_field = Entry(frame_input, font='Arial 15 bold', width=24, state="readonly")
input_field.pack(fill=BOTH)

root.mainloop()

Далее создадим кортеж, в котором будут храниться кнопки будущего калькулятора:

from tkinter import *

root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

input_field = Entry(frame_input, font='Arial 15 bold', width=24, state="readonly")
input_field.pack(fill=BOTH)

buttons = (('7', '8', '9', '/', '4'),
           ('4', '5', '6', '*', '4'),
           ('1', '2', '3', '-', '4'),
           ('0', '.', '=', '+', '4')
           )

root.mainloop()

Создадим пустую переменную expression строкового типа данных. Она нам пригодится для избежания ошибок в будущем. Также добавим кнопку, которая в последующем
будет служить для очищения текстового поля:

from tkinter import *

root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

input_field = Entry(frame_input, font='Arial 15 bold', width=24, state="readonly")
input_field.pack(fill=BOTH)

buttons = (('7', '8', '9', '/', '4'),
           ('4', '5', '6', '*', '4'),
           ('1', '2', '3', '-', '4'),
           ('0', '.', '=', '+', '4')
           )

expression = ""

button = Button(root, text='C', command=lambda: bt_clear())
button.grid(row=1, column=3, sticky="nsew")

root.mainloop()

Теперь добавим основные кнопки калькулятора с помощью цикла. И в основном, и во вложенном циклах будет по 4 итерации. Во вложенном цикле создаётся кнопка, с шириной 2, и высотой 3. Текстом будет являться поиндексное значение из кортежа buttons. Команда будет задаваться с помощью анонимной функции lambda, позиционироваться кнопки будут с помощью метода grid():

from tkinter import *

root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

input_field = Entry(frame_input, font='Arial 15 bold', width=24, state="readonly")
input_field.pack(fill=BOTH)

buttons = (('7', '8', '9', '/', '4'),
           ('4', '5', '6', '*', '4'),
           ('1', '2', '3', '-', '4'),
           ('0', '.', '=', '+', '4')
           )

expression = ""

button = Button(root, text='C', command=lambda: bt_clear())
button.grid(row=1, column=3, sticky="nsew")

for row in range(4):
    for col in range(4):
        Button(root, width=2, height=3, text=buttons[row][col],
               command=lambda row=row, col=col: btn_click(buttons[row][col])).grid(row=row + 2, column=col, sticky="nsew", padx=1, pady=1)

root.mainloop()

Создадим функцию btn_click(), и в качестве аргумента укажем item. Сделаем переменную expression глобальной, после чего добавим конструкцию try … except:

from tkinter import *


def btn_click(item):
    global expression
    try:
        pass
    except:
        pass


root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

input_field = Entry(frame_input, font='Arial 15 bold', width=24, state="readonly")
input_field.pack(fill=BOTH)

buttons = (('7', '8', '9', '/', '4'),
           ('4', '5', '6', '*', '4'),
           ('1', '2', '3', '-', '4'),
           ('0', '.', '=', '+', '4')
           )

expression = ""

button = Button(root, text='C', command=lambda: bt_clear())
button.grid(row=1, column=3, sticky="nsew")

for row in range(4):
    for col in range(4):
        Button(root, width=2, height=3, text=buttons[row][col],
               command=lambda row=row, col=col: btn_click(buttons[row][col])).grid(row=row + 2, column=col, sticky="nsew", padx=1, pady=1)

root.mainloop()

В try мы даём возможность писать в текстовое поле, приведя параметр state в normal. Далее к expression прибавляем item. И вводим результат в текстовое поле:

from tkinter import *


def btn_click(item):
    global expression
    try:
        input_field['state'] = "normal"
        expression += item
        input_field.insert(END, item)
    except:
        pass


root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

input_field = Entry(frame_input, font='Arial 15 bold', width=24, state="readonly")
input_field.pack(fill=BOTH)

buttons = (('7', '8', '9', '/', '4'),
           ('4', '5', '6', '*', '4'),
           ('1', '2', '3', '-', '4'),
           ('0', '.', '=', '+', '4')
           )

expression = ""

button = Button(root, text='C', command=lambda: bt_clear())
button.grid(row=1, column=3, sticky="nsew")

for row in range(4):
    for col in range(4):
        Button(root, width=2, height=3, text=buttons[row][col],
               command=lambda row=row, col=col: btn_click(buttons[row][col])).grid(row=row + 2, column=col, sticky="nsew", padx=1, pady=1)

root.mainloop()

Зададим условие, что если на;ата кнопка «равно», то будет подсчитываться результат методом eval(). После чего результат будет выведен в текстовое поле, а expression обнулится. В конце try снова замораживаем текстовое поле:

from tkinter import *


def btn_click(item):
    global expression
    try:
        input_field['state'] = "normal"
        expression += item
        input_field.insert(END, item)

        if item == '=':
            result = str(eval(expression[:-1]))
            input_field.insert(END, result)
            expression = ""

        input_field['state'] = "readonly"
    except:
        pass


root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

input_field = Entry(frame_input, font='Arial 15 bold', width=24, state="readonly")
input_field.pack(fill=BOTH)

buttons = (('7', '8', '9', '/', '4'),
           ('4', '5', '6', '*', '4'),
           ('1', '2', '3', '-', '4'),
           ('0', '.', '=', '+', '4')
           )

expression = ""

button = Button(root, text='C', command=lambda: bt_clear())
button.grid(row=1, column=3, sticky="nsew")

for row in range(4):
    for col in range(4):
        Button(root, width=2, height=3, text=buttons[row][col],
               command=lambda row=row, col=col: btn_click(buttons[row][col])).grid(row=row + 2, column=col, sticky="nsew", padx=1, pady=1)

root.mainloop()

В except мы будем ловить ошибку ZeroDivisionError, и говорить, что деление на 0 запрещено.
Также добавим ошибку синтаксиса, при которой будет просто выводиться слово «Ошибка»:

from tkinter import *


def btn_click(item):
    global expression
    try:
        input_field['state'] = "normal"
        expression += item
        input_field.insert(END, item)

        if item == '=':
            result = str(eval(expression[:-1]))
            input_field.insert(END, result)
            expression = ""

        input_field['state'] = "readonly"
    except ZeroDivisionError:
        input_field.delete(0, END)
        input_field.insert(0, 'Ошибка (деление на 0)')
    except SyntaxError:
        input_field.delete(0, END)
        input_field.insert(0, 'Ошибка')


root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

input_field = Entry(frame_input, font='Arial 15 bold', width=24, state="readonly")
input_field.pack(fill=BOTH)

buttons = (('7', '8', '9', '/', '4'),
           ('4', '5', '6', '*', '4'),
           ('1', '2', '3', '-', '4'),
           ('0', '.', '=', '+', '4')
           )

expression = ""

button = Button(root, text='C', command=lambda: bt_clear())
button.grid(row=1, column=3, sticky="nsew")

for row in range(4):
    for col in range(4):
        Button(root, width=2, height=3, text=buttons[row][col],
               command=lambda row=row, col=col: btn_click(buttons[row][col])).grid(row=row + 2, column=col, sticky="nsew", padx=1, pady=1)

root.mainloop()

Теперь добавим функцию для очищения текстового поля. Внутри неё делаем переменную expression глобальной, опять же размораживаем текстовое поле, очищаем его, и снова замораживаем:

from tkinter import *


def btn_click(item):
    global expression
    try:
        input_field['state'] = "normal"
        expression += item
        input_field.insert(END, item)

        if item == '=':
            result = str(eval(expression[:-1]))
            input_field.insert(END, result)
            expression = ""

        input_field['state'] = "readonly"
    except ZeroDivisionError:
        input_field.delete(0, END)
        input_field.insert(0, 'Ошибка (деление на 0)')
    except SyntaxError:
        input_field.delete(0, END)
        input_field.insert(0, 'Ошибка')


def bt_clear():
    global expression
    expression = ""
    input_field['state'] = "normal"
    input_field.delete(0, END)
    input_field['state'] = "readonly"


root = Tk()
root.geometry("268x288")
root.title("Калькулятор")
root.resizable(0, 0)

frame_input = Frame(root)
frame_input.grid(row=0, column=0, columnspan=4, sticky="nsew")

input_field = Entry(frame_input, font='Arial 15 bold', width=24, state="readonly")
input_field.pack(fill=BOTH)

buttons = (('7', '8', '9', '/', '4'),
           ('4', '5', '6', '*', '4'),
           ('1', '2', '3', '-', '4'),
           ('0', '.', '=', '+', '4')
           )

expression = ""

button = Button(root, text='C', command=lambda: bt_clear())
button.grid(row=1, column=3, sticky="nsew")

for row in range(4):
    for col in range(4):
        Button(root, width=2, height=3, text=buttons[row][col],
               command=lambda row=row, col=col: btn_click(buttons[row][col])).grid(row=row + 2, column=col, sticky="nsew", padx=1, pady=1)

root.mainloop()

Итог:

GUI Калькулятор на Python tkinter

Заключение

В ходе статьи мы с Вами написали код для GUI калькулятора на языке программирования Python с использованием модуля tkinter. Надеюсь Вам понравилась статья, желаю удачи и успехов! 🙂

Admin
Admin
IT Start