Событие выделения текста в TKinter

Я пишу GUI с использованием TKinter. И столкнулся с проблемой, на которую я не нашел решения:

В моём интерфейсе есть поле для ввода (Entry). Пользователь вводит в него некую информацию. Мне нужно что-бы пользователь не мог выделить текст в этом поле. Это важно.

Я пробовал решить эту проблему тем, что создавал поток с помощью Threading, и в бесконечном цикле очищал выделение с помощью selection_clear(). Но сомневаюсь что это хорошее решение. Может есть способ отслеживать событие выделения текста в Entry?


Ответы (1 шт):

Автор решения: GrAnd

Не знаю есть ли нативный способ сделать это кодом на Питоне... Но т.к. в tkinter доступен интерпретатор Tcl/Tk, то через Tcl можно перехватить (переопределить) процедуру работы с созданным виджетом (в Tcl каждый виджет создаёт собственную команду (имеющую такое же имя как и сам виджет) для управления собой). А в этой процедуре просто ничего не делать, если её вызвали с параметрами selection range (установка выделения), а для остальных вариантов вызова передавать управление старой процедуре. Эта блокировка будет работать даже с дефолтными биндингами, т.к. они тоже работают с виджетом через использование этой процедуры.

import tkinter as tk
from tkinter import ttk

def set_entry_no_select(root, entry):
    root.eval(f"""
        rename {entry} {entry}_orig
        proc {entry} args {{
            if {{[string match {{se*}}    [lindex $args 0]] && 
                 [string match {{[atr]*}} [lindex $args 1]]}} {{
                # disable "selection adjust|to|range" sub-commands
                return
            }}
            tailcall {entry}_orig {{*}}$args
        }}
    """)

root = tk.Tk()

text = tk.StringVar(root, "Entry Entry Entry") 
entry = tk.Entry(textvariable=text)
set_entry_no_select(root, entry)
entry.pack()

text2 = tk.StringVar(root, "TtkEntry TtkEntry TtkEntry") 
entry2 = ttk.Entry(textvariable=text2)
set_entry_no_select(root, entry2)
entry2.pack()

root.mainloop()
→ Ссылка