Как ввести текст в два текстовых виджета, просто войдя в один и тот же виджет

Мне нужен метод, из которого я могу вставлять текст в два виджета, вводя текст в один текстовый виджет. Просто в программировании я хочу связать все функции и события текстового виджета с другим текстовым виджетом. я пытался

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>)

но это не очень хороший вариант, потому что он требует времени и показывает некоторую задержку, а когда текст идет долго, то задержка большая.


person Kumar Saptam    schedule 08.10.2019    source источник
comment
У вас синтаксическая ошибка, и insert вызовет insert() takes at least 3 arguments (2 given)   -  person Kenly    schedule 08.10.2019
comment
Я обновил свой ответ, чтобы использовать встроенные трекеры для текстовых виджетов для обновления при изменении. Дайте мне знать, если это то, что вы искали.   -  person Mike - SMT    schedule 08.10.2019


Ответы (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()
person Bryan Oakley    schedule 08.10.2019
comment
Это сработало как по маслу, спасибо Брайану Окли, ты великий человек. - person Kumar Saptam; 10.10.2019

Самый быстрый способ обновить текст во втором поле, который я нашел, — это использовать 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()
person Mike - SMT    schedule 08.10.2019
comment
IT показывает задержку, потому что я использую подсветку синтаксиса, поэтому этот класс использует большую часть поиска и замены, а также добавляет слишком много тегов к тексту, что приводит к замедлению окраски, но спасибо за ваш ответ, иначе ответ Брайана работал более эффективно. - person Kumar Saptam; 10.10.2019