Не работает декоратор, выдаёт ошибку TypeError: BasicButtons.my_decorator() missing 1 required positional argument: 'func'
В GUI tkinter разрабатываю калькулятор. При нажатии на кнопку С (метод clear_text_field) ранее введенные цифры удаляются и появляется 0. Для оптимизации метода clear_text_field внедрил декоратор "my_decorator", но почему-то выдаёт ошибку:
TypeError: BasicButtons.my_decorator() missing 1 required positional argument: 'func'
Если его закомментировать, а метод раскомментировать всё работает. В чем ошибка?
from tkinter import *
from tkinter.ttk import Frame, Button, Style
import functools
class BasicButtons(Frame):
def __init__(self, master):
super().__init__()
self.memory = "0"
self.my_window()
def padding_button(self): # rr отделяем кнопки друг от друга padding в 5px
for el in range(5):
self.columnconfigure(el, pad=5)
for el1 in range(6):
self.rowconfigure(el1, pad=5)
def make_digit_button(self, digit): # rr создание цифровых кнопок
return Button(self, text=digit, style='btn_color.TButton', command=lambda: self.add_element(digit))
def my_window(self):
Style().configure("TFrame") # background="blue"
Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 12', foreground='#F8F8FF', borderwidth=2,
relief=GROOVE)
Style().configure('one.TButton', background='red')
# yy настройка фона и текста при наведении мыши
Style().configure('btn_color.TButton', foreground='#007BA7')
Style().map("btn_color.TButton",
foreground=[('pressed', '#4da3c1'), ('active', '#71b5cd')],
background=[('pressed', '!disabled', '#e1e1e1'), ('active', '#ececec')])
self.padding_button() # yy отделяем кнопки друг от друга padding в 5px
# yy показываем цифровое поле
self.text_field = Text(self, foreground='black', padx=10, pady=5, relief='sunken', bd=5,
font=('serif', 14, 'bold'),
height=1, width=10)
self.text_field.insert('end', '0', 'right') # yy центрирование справа
self.text_field.tag_configure('right', justify='right')
self.text_field['state'] = 'disable'
self.text_field.grid(row=0, columnspan=5, sticky='we', padx=10, pady=(5, 10))
Button(self, text="C", style='one.TButton', command=lambda: self.clear_text_field()).grid(row=1, column=4)
# yy Оформление кнопок
self.make_digit_button('7').grid(row=3, column=0)
self.make_digit_button('8').grid(row=3, column=1)
self.make_digit_button('9').grid(row=3, column=2)
self.make_digit_button('4').grid(row=4, column=0)
self.make_digit_button('5').grid(row=4, column=1)
self.make_digit_button('6').grid(row=4, column=2)
self.make_digit_button('1').grid(row=5, column=0)
self.make_digit_button('2').grid(row=5, column=1)
self.make_digit_button('3').grid(row=5, column=2)
self.make_digit_button('0').grid(row=6, columnspan=2, sticky='we', padx=2, pady=(3, 4))
self.make_digit_button('.').grid(row=6, column=2)
def my_decorator(self, func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
self.text_field['state'] = 'normal'
self.text_field.delete(1.0, END)
func(*args, **kwargs)
self.text_field.tag_configure('right', justify='right')
self.text_field['state'] = 'disable'
return
return wrapper
@my_decorator
def clear_text_field(self): # rr удаление информации в текстовом поле
self.text_field.insert(1.0, '0', 'right')
# def clear_text_field(self): # rr удаление информации в текстовом поле
# self.text_field['state'] = 'normal'
# self.text_field.delete(1.0, END)
# self.text_field.insert(1.0, '0', 'right')
# self.text_field.tag_configure('right', justify='right')
# self.text_field['state'] = 'disable'
def add_element(self, elem): # rr вывод цифр на дисплей
self.text_field['state'] = 'normal'
value = self.text_field.get(1.0, 'end').strip() # yy удаляем перенос на другую строку
if (value[0] == '0' and elem == '.') or (value[0] == '0' and len(value) >= 2 and value[1] == '.'):
self.text_field.delete(1.0, END) # yy очищаю строку
self.text_field.insert(1.0, value + elem, 'right') # yy выравниваю текст справа
elif value[0] == '0':
self.text_field.delete(1.0, END)
self.text_field.insert(1.0, elem, 'right')
else:
self.text_field.delete(1.0, END)
self.text_field.insert(1.0, value + elem, 'right')
self.text_field.tag_configure('right', justify='right')
self.text_field['state'] = 'disable'
class Calculator(Tk):
def __init__(self):
super().__init__()
self.frame_a = BasicButtons(self)
self.frame_a.pack(side=LEFT, padx=10, pady=10)
if __name__ == '__main__':
app = Calculator()
app.title("Калькулятор - обычный режим")
app.mainloop()
Ответы (1 шт):
Автор решения: Amgarak
→ Ссылка
В декоратор мы передаём сам метод, а уже в обёртке принимаем все его параметры в том числе и объект класса:
def my_decorator(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
self.text_field['state'] = 'normal'
self.text_field.delete(1.0, END)
func(self, *args, **kwargs)
self.text_field.tag_configure('right', justify='right')
self.text_field['state'] = 'disable'
return
return wrapper