Рассмотрим, как разработать полноценное объектно-ориентированное приложение Tkinter в Python.
Вам предстоит преобразовать приложение temperature converter в новое, использующее подход объектно-ориентированного программирования:

- Сначала определим класс с именем TemperatureConverter. Класс имеет один статический метод, который преобразует температуру из градусов Фаренгейта в градусы Цельсия:
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showerror
class TemperatureConverter:
@staticmethod
def fahrenheit_to_celsius(f):
return(f - 32) * 5 / 9
- Во-вторых, определите класс ConverterFrame, который наследуется от класса ttk.Frame. Класс ConverterFrame будет отвечать за создание виджетов и обработку событий:
class ConverterFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
# field options
options = {'padx': 5, 'pady': 5}
# temperature label
self.temperature_label = ttk.Label(self, text="Fahrenheit")
self.temperature_label.grid(column=0, row=0, sticky=tk.W, **options)
# temperature entry
self.temperature = tk.StringVar()
self.temperature_entry = ttk.Entry(self, textvariable=self.temperature)
self.temperature_entry.grid(column=1, row=0, **options)
self.temperature_entry.focus()
self.convert_button = ttk.Button(self, text="Convert")
self.convert_button['command'] = self.convert
self.convert_button.grid(column=2, row=0, sticky=tk.W, **options)
# result label
self.result_label = ttk.Label(self)
self.result_label.grid(row=1, columnspan=3, **options)
# add padding to the frame and show it
self.grid(padx=10, pady=10, sticky=tk.NSEW)
def convert(self):
""" Handle button click event
"""
try:
f = float(self.temperature.get())
c = TemperatureConverter.fahrenheit_to_celsius(f)
result = f'{f} Fahrenheit = {c:.2f} Celsius'
self.result_label.config(text=result)
except ValueError as error:
showerror(title="Error", message=error)
Как это работает:
- ConverterFrame нуждается в контейнере, поэтому его метод __init__() имеет аргумент контейнера.
- Внутри метода __init__() класса ConverterCFrame вызовите метод __init__() его суперкласса.
- Назначьте виджеты объекту self, чтобы можно было ссылаться на них в других методах класса ConverterFrame.
- Назначьте параметр команды кнопки «конвертировать» методу self.convert.
В-третьих, определите класс App, который наследуется от класса tk.Tk:
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Temperature Converter')
self.geometry('300x70')
self.resizable(False, False)
- Наконец, загрузите приложение из блока if __name__ == «__main__»:
if __name__ == "__main__":
app = App()
ConverterFrame(app)
app.mainloop()
Соединим все вместе:
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showerror
class TemperatureConverter:
@staticmethod
def fahrenheit_to_celsius(f):
return(f - 32) * 5 / 9
class ConverterFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
# field options
options = {'padx': 5, 'pady': 5}
# temperature label
self.temperature_label = ttk.Label(self, text="Fahrenheit")
self.temperature_label.grid(column=0, row=0, sticky=tk.W, **options)
# temperature entry
self.temperature = tk.StringVar()
self.temperature_entry = ttk.Entry(self, textvariable=self.temperature)
self.temperature_entry.grid(column=1, row=0, **options)
self.temperature_entry.focus()
self.convert_button = ttk.Button(self, text="Convert")
self.convert_button['command'] = self.convert
self.convert_button.grid(column=2, row=0, sticky=tk.W, **options)
# result label
self.result_label = ttk.Label(self)
self.result_label.grid(row=1, columnspan=3, **options)
# add padding to the frame and show it
self.grid(padx=10, pady=10, sticky=tk.NSEW)
def convert(self):
""" Handle button click event
"""
try:
f = float(self.temperature.get())
c = TemperatureConverter.fahrenheit_to_celsius(f)
result = f'{f} Fahrenheit = {c:.2f} Celsius'
self.result_label.config(text=result)
except ValueError as error:
showerror(title="Error", message=error)
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Temperature Converter')
self.geometry('300x70')
self.resizable(False, False)
if __name__ == "__main__":
app = App()
ConverterFrame(app)
app.mainloop()
