Разработка объектно-ориентированного приложения Tkinter в Python
Рассмотрим, как разработать полноценное объектно-ориентированное приложение 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()