Как отключить tkinter listbox во время функции - PullRequest
0 голосов
/ 06 марта 2019

У меня есть графический интерфейс, созданный в Python 3.x с использованием tkinter из сообщества Visual Studio 2017.Создается верхний виджет, в который добавляются рамка и список.Когда пользователь нажимает на запись в списке, индекс выбора передается в twoSecondFunction(), что занимает около 2 секунд.

Как я могу запретить пользователю делать еще один выбор в течение этого времени?

Я пытался использовать строку myListbox.config(state=tkinter.DISABLED), чтобы отключить список, когда выбор былсделал и снова включил список только после завершения twoSecondFunction().

Когда я запускаю код из Visual Studio myListbox события клика обрабатываются myListboxSelection и 'twoSecondFunction ()' и print()называются.Это окно не отвечает на время действия myListboxSelection().

, если пользователь нажимает на другую запись до

Функция завершена

был выведен myListboxSelection() вызывается в другой раз.

Я могу поставить в очередь более 10 команд, быстро щелкнув перед выводом «Функция завершена».Графический интерфейс пользователя не отвечает на все события в очереди и реагирует на другие команды только после выполнения всех вызовов myListboxSelection () в очереди.

Я попытался удалить строку myListbox.config(state=tkinter.NORMAL), и тогда регистрируется только один щелчок дляпродолжительность программы, поэтому myListbox.config(state=tkinter.DISABLED) работает, как и должно, когда она вызывается.myListbox также не работает.

Я также добавил дополнительные print() строки по всей программе, чтобы все операции происходили в ожидаемом порядке.

Кажется, что логика выполняется намного быстрее, чем сам графический интерфейс, поэтому myListbox включается гораздо быстрее, чем реагирует графический интерфейс.Я не вижу myListbox серым во время выполнения функции twoSecondFunction ().

Это потому, что myListbox.config(state=tkinter.DISABLED) вступает в силу только после того, как обработчик событий завершит свое выполнение?Т.е. myListbox.config(state=tkinter.DISABLED) никогда не вступает в силу, потому что myListbox.config(state=tkinter.NORMAL) установлено до того, как myListbox фактически отключено?

import tkinter #For the GUI tools

#Event handler for mouse click of myListbox
def myListboxSelection(event):
    myListbox.config(state=tkinter.DISABLED) #Disable myListbox
    myListboxIndex = int(myListbox.curselection()[0]) #Get selection index
    twoSecondFunction(myListboxIndex) #Call function that takes 2 seconds
    print("Function finished") #Output to console on completion
    myListbox.config(state=tkinter.NORMAL) #Enable Listbox

#Create GUI
GUITopWidget = tkinter.Tk(screenName = "myListboxGUI") #Create Top Level Widget
myFrame = tkinter.Frame(GUITopWidget, name = "myFrame") #Create frame
myFrame.pack() #Pass to Geometry Manager
myListbox = tkinter.Listbox(authoritiesListFrame) #Create myListbox
myListbox.bind('<<ListboxSelect>>', myListboxSelection) #Bind mouse click event
populateListbox(myListbox) #Add entries to the listbox
myListbox.pack() #Pass to Geometry Manager

#Run the GUI loop
GUITopWidget.mainloop() 

1 Ответ

0 голосов
/ 07 марта 2019

Похоже, что если у вас есть обработчик событий и используется mainloop(), он действительно останавливает выполнение любой логики во время обратного вызова. Вместо этого определите цикл, который может обрабатывать вызовы событий, другую логику и вызов update() в графическом интерфейсе вручную:

import tkinter #For the GUI tools

rootWindowClosed = False
requestQueued  = False #True request is queued
myListboxIndex= -1 #Set to -1 between requests

#Event handler for mouse click of myListbox
def myListboxSelection(event):
    myListbox.config(state=tkinter.DISABLED) #Disable myListbox
    myListboxIndex = int(myListbox.curselection()[0]) #Get selection index

#On closing of root window
def closeGUIHandler():
    #Set the rootWindowClosed flag to True
    global rootWindowClosed
    rootWindowClosed = True
    #Destroy GUI Root
    GUITopWidget.destroy()

#Create GUI
GUITopWidget = tkinter.Tk(screenName = "myListboxGUI") #Create Top Level Widget
GUITopWidget.protocol("WM_DELETE_WINDOW", closeGUIHandler) #Set delete window protocol
myFrame = tkinter.Frame(GUITopWidget, name = "myFrame") #Create frame
myFrame.pack() #Pass to Geometry Manager
myListbox = tkinter.Listbox(authoritiesListFrame) #Create myListbox
myListbox.bind('<<ListboxSelect>>', myListboxSelection) #Bind mouse click event
populateListbox(myListbox) #Add entries to the listbox
myListbox.pack() #Pass to Geometry Manager

#Run the GUI loop
while rootWindowClosed == False:
    #If requestQueued then execute queued request
    if requestQueued  == True:
        twoSecondFunction(myListboxIndex) #Call function that takes 2 seconds
        myListbox.config(state=tkinter.NORMAL) #Enable Listbox
        myListboxIndex = -1

    #Update GUI window if not closed
    time.sleep(0.05) #Sleep for 50 ms to allow event handling before executing code
    if rootWindowClosed == False:
        GUIRootWidget.update()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...