#python #user-interface #tkinter #tkinter-text
#python #пользовательский интерфейс #tkinter #tkinter-текст
Вопрос:
Я пытался заменить (во время выполнения) унаследованный метод insert() для подкласса tkinter.Текст. Метод замены выполняет несколько строк кода перед вызовом метода вставки () родительского класса (tkinter.Text). Однако во время выполнения python выдает следующую ошибку.
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/tkinter/__init__.py", line 1885, in __call__
return self.func(*args)
File ".../expts/test.py", line 20, in callback
text.insert("1.0", "howdy")
File ".../expts/test.py", line 14, in new_insert
tk.Text.insert(text, index, chars, *args)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/tkinter/__init__.py", line 3740, in insert
self.tk.call((self._w, 'insert', index, chars) args)
AttributeError: type object 'Text' has no attribute 'tk'
Следующий код представляет собой упрощенную версию моего основного кода.
import tkinter as tk
import types
class TextChild(tk.Text):
def __init__(self, *args, **kwargs):
tk.Text.__init__(self, *args, **kwargs)
root = tk.Tk()
text = TextChild(root)
text.pack()
def new_insert(text, index, chars, *args):
print("Does some work...")
tk.Text.insert(text, index, chars, *args)
text.insert = types.MethodType(new_insert, tk.Text)
def callback():
global text
text.insert("1.0", "howdy")
button = tk.Button(master=root,text="Button", command=callback)
button.pack()
root.mainloop()
Ответ №1:
Это проще сделать внутри унаследованного класса:
class TextChild(tk.Text):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def insert(self, index, chars, *args):
print("Does some work ...")
# call original insert()
super().insert(index, chars, *args)
Комментарии:
1. Я разрабатываю плагин для существующего приложения. Итак, я не могу обновить существующие определения. Я могу изменять методы / обратные вызовы только в течение срока службы плагина.
2. @SamZeleke Тогда в вашем случае
TextChild
нет необходимости, и вы можете использоватьlambda
вместо этого:text.insert = lambda *args: new_insert(text, *args)
.3. Вы правы. TextChild так же прост, потому что я упростил код для вопроса. Класс на самом деле намного больше.
Ответ №2:
Чтобы обратиться к вашему исходному методу, вы смешиваете аргументы для types.MethodType
. Аргументами являются метод и объект.
text.insert = types.MethodType(new_insert, text)