【问题标题】:PySimpleGUI reads in button event despite button being disabled at the time尽管按钮当时被禁用,PySimpleGUI 仍会读取按钮事件
【发布时间】:2019-09-03 18:11:20
【问题描述】:

我有一个基于 PySimpleGUI(PySimpleGUI 3.4.2.、Python 3.7.2、macOS Mojave 10.14.6)的 GUI,除了 按钮似乎被禁用但似乎正在触发之外,它工作正常。

用户听 3 个连续的声音,并通过单击按钮在我的 GUI 中给出评分。当用户收听声音时,按钮被禁用,因此在所有声音结束之前无法给出响应。按钮在 GUI 中成功显示为灰色 (window.FindElement(button_label).Update(disabled=False))。但是,如果按下禁用的按钮,则 GUI 会在启用按钮后立即接受此响应(就好像响应事件已排队一样),即使在启用按钮后没有按下任何按钮,这也会使 GUI 混乱(例如,意外双击被视为对两组 3 个声音的响应。)

我试图找到答案,但我没有找到 PySimpleGUI 的任何答案。我尝试了不同的方法在声音演示期间暂停代码(sd.wait 和 time.sleep),以防在播放声音时以某种方式在后台启用按钮。我试图弄乱读入的事件以解决该问题,但无济于事。我之前在使用 .Update() 方法启用这些按钮时遇到了麻烦,并且只有在添加 window.Refresh() 行后按钮才会变灰。 我必须以某种方式确保按钮在禁用时不接受任何输入。

这是从真实版本严重压缩的示例代码。这是一个工作版本,其中响应按钮在提供响应后禁用 3 秒,并打印所有收集的响应。这可视化按钮在禁用时收集响应。

import PySimpleGUI as sg
import time

response_buttons = ['b1', 'b2', 'b3', 'b4', 'b5']
current_event=[]
layout = [[sg.Button('start', key='start')],
            [sg.Button('text5', key='b5')],
            [sg.Button('text4', key='b4')],
            [sg.Button('text3', key='b3')],
            [sg.Button('text2', key='b2')],
            [sg.Button('text1', key='b1')]]
window = sg.Window('GUI test').Layout(layout).Finalize()
for button_label in response_buttons:
    window.FindElement(button_label).Update(disabled=True)
window.Refresh()

while True:
    # Read the Window
    event, values = window.Read()
    print(event)
    if event is None:
        break
    # Take appropriate action based on button
    if event == 'start':
        window.FindElement('start').Update(disabled=True)
        for button_label in response_buttons:
            window.FindElement(button_label).Update(disabled=False)
        window.Refresh()
    if event in response_buttons:
        # collect and store response
        current_event = current_event + [event]
        # disable the buttons during sound presentation
        for button_label in response_buttons:
            window.FindElement(button_label).Update(disabled=True)
        window.Refresh()
        time.sleep(3)
        for button_label in response_buttons:
            window.FindElement(button_label).Update(disabled=False)

目标是用户可以在听完声音后按一次按钮,然后禁用所有按钮,直到下一组声音结束。双击按钮并在禁用状态下单击按钮不会导致注册响应。

【问题讨论】:

    标签: python-3.x pysimplegui


    【解决方案1】:

    你的逻辑不好。按下 text 按钮后,您没有正确设置按钮的状态。我去掉了所有声音的东西,只留下了 GUI,所以我们只看那个,只有那个。

    当您单击Text 按钮时,问题就出现了。看看你的代码......你在 if 块中做的最后一件事是启用所有Text 按钮。它们应该被禁用并且应该启用“开始”按钮。

    这是一个工作演示,我相信它可以按照您想要的方式设置按钮状态。首先仅启用启动。如果单击,它将被禁用并启用文本按钮。一切正常。

    import PySimpleGUI as sg
    
    response_buttons = ['b1', 'b2', 'b3', 'b4', 'b5']
    current_event=[]
    layout = [[sg.Button('start', key='start')],
                [sg.Button('text5', key='b5')],
                [sg.Button('text4', key='b4')],
                [sg.Button('text3', key='b3')],
                [sg.Button('text2', key='b2')],
                [sg.Button('text1', key='b1')]]
    window = sg.Window('GUI test').Layout(layout).Finalize()
    for button_label in response_buttons:
        window.FindElement(button_label).Update(disabled=True)
    window.Refresh()
    
    while True:
        # Read the Window
        event, values = window.Read()
        if event is None:
            break
        # Take appropriate action based on button
        if event == 'start':
            window.FindElement('start').Update(disabled=True)
            for button_label in response_buttons:
                window.FindElement(button_label).Update(disabled=False)
            window.Refresh()
        if event in response_buttons:
            # collect and store response
            current_event = current_event + [event]
            # disable the buttons during sound presentation
            for button_label in response_buttons:
                window.FindElement(button_label).Update(disabled=True)
            window.Refresh()
            window.FindElement('start').Update(disabled=False)
    window.Close()
    
    

    【讨论】:

    • 您好,感谢您的回复。我认为我没有很好地解释 GUI。基本上,您只需在最开始时按开始即可开始实验。然后出现声音,您使用其中一个文本按钮进行评分,这会自动开始在回调中显示下一个声音。这就是为什么启动按钮不再启用的原因。一般来说,按钮看起来就像我想要的那样,除了禁用的按钮仍然在我的代码中注册响应。
    • 当您运行我的代码时,按钮是否正确?另外,当我禁用它们时,它们是否在您的计算机上被禁用?当您单击我的代码中的“禁用按钮”之一时,它有什么作用吗?换句话说,我的程序是否按您期望的那样工作(您的程序没有按您期望的方式工作)?如果是这样,那么您就有了一个简单明了的错误。
    • 哦,我已经告诉过你你的错误是什么了。您在 if 块的末尾重新启用按钮。在计时器 window.FindElement(button_label).Update(disabled=False) 之后。这重新启用了您想要禁用的所有按钮。
    • 不,这正是我希望代码执行的操作。我不希望用户每次新的重复(声音演示)都必须按开始。对其中一个文本按钮的响应会自动开始下一次重复(声音呈现),在此期间按钮被禁用,一旦声音播放完毕,按钮就会自动启用。这是所希望的。您的代码成功禁用了按钮,但是,每次都按 start 不是一个选项,也不应该是必需的。
    • 那你需要再次调用Read。我不相信 cmets 是解决此问题的最佳场所。 GitHub 问题是移动它的正确位置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 2021-03-03
    • 2016-09-03
    • 2013-02-08
    • 2020-07-05
    • 1970-01-01
    相关资源
    最近更新 更多