Как ввести текст в два текстовых виджета, просто введя в один и тот же виджет
Мне нужен метод, с помощью которого я могу вставлять текст в два виджета, вводя текст в один текстовый виджет. Просто в программировании я хочу привязать все функции и события текстового виджета к другому текстовому виджету. я пробовал
txt=Text(root,height=300,width=300)
txt.pack()
text=Text(root,height=300,width=300)
text.pack()
def func(event):
text.delete("1.0","end")
text.insert(INSERT,txt.get("1.0","end"))
txt.bind(func,<Any-KeyPress>)
но это не лучший вариант, потому что он требует времени и показывает некоторую задержку и некоторую долгую задержку, когда текст становится длинным.
2 ответа
Если вы хотите, чтобы содержимое двух текстовых виджетов было идентичным, у текстового виджета есть малоиспользуемая функция, известная как одноранговые виджеты. По сути, у вас может быть несколько текстовых виджетов с одной и той же базовой структурой данных.
В канонической документации tcl/tk одноранговые узлы описаны следующим образом:
Текстовый виджет имеет отдельное хранилище всех данных, касающихся текстового содержимого каждой строки, меток, тегов, изображений и окон, а также стека отмены.
Хотя к этому хранилищу данных нельзя получить доступ напрямую (т.е. без текстового виджета в качестве посредника), можно создать несколько текстовых виджетов, каждый из которых представляет разные представления для одних и тех же базовых данных. Такие текстовые виджеты известны как одноранговые текстовые виджеты.
К сожалению, поддержка пиринга текстовых виджетов в tkinter не завершена. Однако можно создать новый класс виджетов, использующий функцию пиринга.
Следующее определяет новый виджет, TextPeer
. Он берет другой текстовый виджет в качестве своего хозяина и создает однорангового узла:
import tkinter as tk
class TextPeer(tk.Text):
"""A peer of an existing text widget"""
count = 0
def __init__(self, master, cnf={}, **kw):
TextPeer.count += 1
parent = master.master
peerName = "peer-{}".format(TextPeer.count)
if str(parent) == ".":
peerPath = ".{}".format(peerName)
else:
peerPath = "{}.{}".format(parent, peerName)
# Create the peer
master.tk.call(master, 'peer', 'create', peerPath, *self._options(cnf, kw))
# Create the tkinter widget based on the peer
# We can't call tk.Text.__init__ because it will try to
# create a new text widget. Instead, we want to use
# the peer widget that has already been created.
tk.BaseWidget._setup(self, parent, {'name': peerName})
Вы используете это так же, как вы используете Text
виджет. Вы можете настроить одноранговый узел так же, как обычный текстовый виджет, но данные будут совместно использоваться (например: вы можете иметь разные размеры, цвета и т. Д. Для каждого однорангового узла)
Вот пример, который создает трех сверстников. Обратите внимание, что при вводе любого из виджетов сразу же обновляются другие. Хотя эти виджеты используют одни и те же данные, каждый может иметь собственное местоположение курсора и выделенный текст.
import tkinter as tk
root = tk.Tk()
text1 = tk.Text(root, width=40, height=4, font=("Helvetica", 20))
text2 = TextPeer(text1, width=40, height=4, background="pink", font=("Helvetica", 16))
text3 = TextPeer(text1, width=40, height=8, background="yellow", font=("Fixed", 12))
text1.pack(side="top", fill="both", expand=True)
text2.pack(side="top", fill="both", expand=True)
text3.pack(side="top", fill="both", expand=True)
text2.insert("end", (
"Type in one, and the change will "
"appear in the other."
))
root.mainloop()
Самый быстрый способ обновить текст во втором поле, который я нашел, - это использовать replace()
а также get()
. Тем не менее, после тестирования вашего примера я действительно не вижу заметной задержки.
Мы можем использовать Modified
событие для управления нашими обновлениями, и после каждого изменения мы можем сообщить text1
который Modified
имеет значение False, поэтому мы получаем обновления при каждом изменении.
Сообщите мне, если это то, что вы искали.
Попробуй это:
import tkinter as tk
def update_text2(_=None):
text2.replace('1.0', 'end', text1.get('1.0', 'end'))
text1.edit_modified(False)
root = tk.Tk()
text1 = tk.Text(root)
text2 = tk.Text(root)
text1.pack()
text2.pack()
text1.bind('<<Modified>>', update_text2)
root.mainloop()