Диалог tkinter выделяет текст родительской записи - PullRequest
0 голосов
/ 22 января 2019

Я пытаюсь продублировать поведение поискового диалога Python Idle, который выделяет текст сзади. Поэтому я ссылаюсь на эту ссылку и создаю свой собственный диалог: http://effbot.org/tkinterbook/tkinter-dialog-windows.htm

Python Idle Search Dialog

Проблема в том, что с self.grab_set() я не могу выделить текст родительского окна, которое вызывает диалог. Я не хочу удалять self.grab_set(), потому что я также не хочу, чтобы пользователи нажимали вокруг при поиске.

Слушатели кнопок, запускаемые по нажатию кнопки, выполняются правильно, как я тестировал в других реализациях диалога. Например, текст заменяется правильно с помощью диалога замены. Поэтому единственной проблемой является то, что текст Entry в родительском окне не выделен / не выделен. На самом деле, текст может быть выделен, если я удаляю self.grab_set(). Тем не менее, диалог теряет фокус и фокус переходит к входу родительского окна, как только я это сделаю. И я не могу нажать Enter, чтобы найти следующий диалог.

Как я могу решить эту проблему? Заранее спасибо!

Моя реализация

--- Update ---

Код тестирования может быть очень простым, как показано ниже.

from tkinter import *

SYSTEM_HIGHLIGHT = 'SystemHighlight'
BUTTON_BORDER = '#b5b5b5'
class FindDialog(Toplevel):
    def __init__(self, master):
        Toplevel.__init__(self, master)
        self.master = master
        self.transient(master)
        self.grab_set()
        self.geometry("+%d+%d" % (master.winfo_rootx() + 50, master.winfo_rooty() + 50))
        self.title('Search Dialog')

        ## Variables
        self.findListner = None

        self.findLabel = Label(self, text = 'Find:')
        self.findEntry = Entry(self)
        self.findEntry.focus()
        self.findEntry.select_range(0, END)
        for i, w in enumerate([self.findLabel, self.findEntry]):
            w.grid(row = 0, column = i, sticky = NSEW)
        self.findEntry.grid(columnspan = 5)
        self.findButton = Button(self, text = 'Find Next', command = self.find)
        self.findButton.grid(row = 1, column = i + 1, sticky = NSEW)
        self.bind('<Return>', lambda event: self.find())

    def setOnFindListner(self, listener):
        '''listner should have the following arguments: dialog, target, direction.'''
        self.findListner = listener

    def find(self):
        if not self.findListner: return
        self.findListner(self, self.findEntry.get())

def find():
    dialog = FindDialog(root)
    dialog.setOnFindListner(onFind)
    root.wait_window(dialog)

def onFind(*args):
    e.focus_set()
    e.select_range(0, END)
    e.icursor(END)

root = Tk()
e = Entry(root)
e.pack()
e.focus()
e.insert(0, 'HelloWorld')
root.bind('<Control-f>', lambda event: find())
root.mainloop()

1 Ответ

0 голосов
/ 22 января 2019

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

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

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

...