Рубрики
Без рубрики

Создание калькулятора ООП и что значит написать библиотеку виджетов

Когда ООП открывает дверь для нового начала. Tagged с Python, OOP, Tkinter, Showdev.

В этом посте мы собираемся кодировать калькулятор ООП, фактически делая его виджет для легкой подключения и воспроизведения. Гибкость и ООП Python – это приятное матч!

Наш скелет

Мы используем Tkinter (на самом деле еще раз, это произносится Tee-kay-inter) и ребята из виджета

from tkinter import *


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


root = Tk()
app = App(root)
root.title('dev.to calculator')
root.mainloop()

мы получаем

И, как обычно, это некоторая информация

Наш калькулятор

Вот нормальный класс

class Calculator:
    def __init__(self, parent, x, y):
        pass

Мы добавляем раму, чтобы удерживать все наши элементы, чтобы мы просто подключаем к раме

class Calculator:
    def __init__(self, parent, x, y):
        self.parent = parent

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

Теперь мы можем добавить наш калькулятор в наше приложение

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

        calc = Calculator(self.master, 0, 0)

мы получаем

Некоторые инициализации в нашем калькуляторе

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

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

        self.string = ''

Эти двое – просто имя шрифта и размер шрифта Self.button_font = (‘Verdana’, 15) self.entry_font = (‘verdana’, 20)

Кадра можно рассматривать как контейнер

В SelfString мы будем хранить то, что мы будем отображать на экране нашего калькулятора

Примечание на сетке

Грид рассказывает нам, где разместить наши элементы, координаты начинаются с 0, 0

Элегантно добавляя элементы

Вместо каждый раз добавлять две строки кода для одной кнопки, мы добавим простую линию, определив это в классе калькулятора

def button(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font)
        self.b.grid(row=x_, column=y_)

а также Используя это так

self.button('7', 1, 0)

То же самое для нашего текстового поля, мы будем отображать наших персонажей

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

Применение

self.entry(0, 0)

State = отключено, чтобы мы ничего не могли написать, поместив наш курсор ColumnSpan расширяет наш элемент в других столбцах

На самом деле добавление их

В нашем классе калькулятора

        self.entry(0, 0)

        self.button('7', 1, 0)
        self.button('8', 1, 1)
        self.button('9', 1, 2)

        self.button('4', 2, 0)
        self.button('5', 2, 1)
        self.button('6', 2, 2)

        self.button('1', 3, 0)
        self.button('2', 3, 1)
        self.button('3', 3, 2)

        self.button('0', 4, 0)

        self.button('+', 1, 3)
        self.button('-', 1, 4)
        self.button('*', 2, 3)
        self.button('/', 2, 4)

        self.button('(', 3, 3)
        self.button(')', 3, 4)

Вот что мы получаем

Добавление кнопок удалить один Char, равные и прозрачные кнопки

У нас будет три кнопки, одна, чтобы удалить символ, если мы ошибочно добавили один, чтобы оценить наш результат, и одна, чтобы полностью очистить дисплей

кнопка оценки

def button_eq(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font)
        self.b.grid(row=x_, column=y_, sticky='we', columnspan=2)

Применение

self.button_eq('=', 4, 1)

Удалить кнопку «Удалить один отбор

def button_rem(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font)
        self.b.grid(row=x_, column=y_)

Применение

self.button_rem('<', 4, 4)

кнопка прозрачной

def button_clear(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font)
        self.b.grid(row=x_, column=y_)

Применение

self.button_clear('clear', 4, 3)

Где мы

Код до сейчас

from tkinter import *

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

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

        self.string = ''

        self.entry(0, 0)

        self.button('7', 1, 0)
        self.button('8', 1, 1)
        self.button('9', 1, 2)

        self.button('4', 2, 0)
        self.button('5', 2, 1)
        self.button('6', 2, 2)

        self.button('1', 3, 0)
        self.button('2', 3, 1)
        self.button('3', 3, 2)

        self.button('0', 4, 0)

        self.button('+', 1, 3)
        self.button('-', 1, 4)
        self.button('*', 2, 3)
        self.button('/', 2, 4)

        self.button('(', 3, 3)
        self.button(')', 3, 4)

        self.button_eq('=', 4, 1)

        self.button_clear('clear', 4, 3)
        self.button_rem('<', 4, 4)

    def button_eq(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font)
        self.b.grid(row=x_, column=y_, sticky='we', columnspan=2)

    def button_rem(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font)
        self.b.grid(row=x_, column=y_)

    def button_clear(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font)
        self.b.grid(row=x_, column=y_)

    def button(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font)
        self.b.grid(row=x_, column=y_)

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


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()

наш графический интерфейс

Добавление логики

Отображение текста делает Textarea нормальным, добавляет затем его снова отключает

    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)

Нажатие на любую кнопку добавляет Char на кнопке на дисплей

    def normal_button_click(self, text_):
        self.string = '' + self.string + text_
        self.display(self.string)

Нажав равную кнопку, оценивая все, что мы пишем. Мы используем Py Eval, поэтому мы можем использовать ** для экспоненциальной

    def equal_button_click(self):
        self.display(eval(self.string))
        self.string = ''   

Удаление одного ЧАР просто уменьшает строку, исключая последний char

    def rem_button_click(self):
        self.string = '' + self.string[0:-1]
        self.display(self.string)

прозрачные кнопки сбрасывают все

    def clear_button_click(self):
        self.display('')
        self.string = ''

Наши кнопки с добавленными командами

нормальная команда добавляется

командование

но команда с параметрами добавляется

command = lambda: self.function (параметр_)

    def button(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font,
            command=lambda: self.normal_button_click(char_))
        self.b.grid(row=x_, column=y_)

    def button_eq(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font,
            command=self.equal_button_click)
        self.b.grid(row=x_, column=y_, sticky='we', columnspan=2)

    def button_rem(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font,
            command=self.rem_button_click)
        self.b.grid(row=x_, column=y_)

    def button_clear(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font,
            command=self.clear_button_click)
        self.b.grid(row=x_, column=y_)

Окончательно Это

наш полный код

from tkinter import *


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

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

        self.string = ''

        self.entry(0, 0)

        self.button('7', 1, 0)
        self.button('8', 1, 1)
        self.button('9', 1, 2)

        self.button('4', 2, 0)
        self.button('5', 2, 1)
        self.button('6', 2, 2)

        self.button('1', 3, 0)
        self.button('2', 3, 1)
        self.button('3', 3, 2)

        self.button('0', 4, 0)

        self.button('+', 1, 3)
        self.button('-', 1, 4)
        self.button('*', 2, 3)
        self.button('/', 2, 4)

        self.button('(', 3, 3)
        self.button(')', 3, 4)

        self.button_eq('=', 4, 1)

        self.button_clear('clear', 4, 3)
        self.button_rem('<', 4, 4)

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

    def button(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font,
            command=lambda: self.normal_button_click(char_))
        self.b.grid(row=x_, column=y_)

    def button_eq(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font,
            command=self.equal_button_click)
        self.b.grid(row=x_, column=y_, sticky='we', columnspan=2)

    def button_rem(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font,
            command=self.rem_button_click)
        self.b.grid(row=x_, column=y_)

    def button_clear(self, char_, x_, y_):
        self.b = Button(
            self.container, text=char_, width=self.button_width,
            height=self.button_height, font=self.entry_font,
            command=self.clear_button_click)
        self.b.grid(row=x_, column=y_)

    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)

    def normal_button_click(self, text_):
        self.string = '' + self.string + text_
        self.display(self.string)

    def equal_button_click(self):
        self.display(eval(self.string))
        self.string = ''

    def rem_button_click(self):
        self.string = '' + self.string[0:-1]
        self.display(self.string)

    def clear_button_click(self):
        self.display('')
        self.string = ''


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()

Изучение гибкости виджета

Поскольку наш калькулятор является виджетом, мы можем добавить Mooore

        calc = Calculator(self.master, 0, 0)
        calc = Calculator(self.master, 0, 1)
        calc = Calculator(self.master, 1, 0)
        calc = Calculator(self.master, 1, 1)

дает нам

На одном экране каждый функционирует как приложение самостоятельно

Так … Библиотека виджетов

Библиотека виджетов – это всего лишь некоторые занятия по графическим интерфейсу. Легко, не так ли?

покрыть IMG Credit: Rawpixels на Unsplash

Оригинал: “https://dev.to/abdurrahmaanj/building-an-oop-calculator-and-what-it-means-to-write-a-widget-library-4560”