如何在使用.bind调用函数时强制Tkinter小部件刷新



我今天下午很无聊,决定用Python实现一个快速打字测试;为了允许它在每个字符之后检查当前单词,我在输入小部件上使用了widgetName.bind("<Key>", functionName),以便在输入小部件内按下任何键时调用该函数。

这工作得很好,函数在每次按键时调用,但是当我使用widgetName.get()从条目小部件收集字符串时,我的问题发生了;.get()不收集小部件的内容,只收集在函数被调用之前小部件中的内容。

例如,如果我在输入小部件中输入' p ',我的函数将打印'A key was pressed',但是它只会向控制台打印空白行。当我继续按下'y'时,字符串'P'被输出到控制台,第三次按下'Py'被输出,依此类推。

这使我相信Tkinter小部件的内容没有更新,因为.bind()调用发生在小部件内容更新之前,因此小部件的内容在一个按键之后。

我需要知道是否有办法解决这个问题,我做了一些研究,发现我可以从函数内调用root.update()widget.update(),这应该强制UI刷新。然而,这并没有帮助,我仍然面临着同样的问题。

我的代码如下

root = Tk()
def keyPress(forSomeReasonThisArgumentFixesABug): ##Argument is because bind passes the event to the function
    entryBox.update()
    entry, word = entryBox.get(), wordBox.get()
    print(entry)
wordBox = Entry(root)
wordBox.grid(row=0, column=0)
entryBox = Entry(root)
entryBox.grid(row=1, column=0)
entryBox.bind("<Key>", keyPress)

有人可以解释我如何将小部件的内容传递给函数(通过参数或使用.get()的函数内)在每次按键时。

提前感谢编辑:我也试过使用.bind()调用的函数来调用另一个函数,它看起来很恶心,仍然不起作用

简短的回答是默认绑定(导致插入字符的绑定)发生在自定义绑定之后的。解决方案是确保绑定发生在默认绑定之后。

这个答案更详细地说明了到底发生了什么:

https://stackoverflow.com/a/11542200/7432

最简单的解决方案是绑定<KeyRelease>而不是<Key>,因为默认绑定发生在按下时。因此,键释放时的绑定将看到插入的字符。

另一个解决方案是更改小部件的绑定标记。这个答案给出了一个工作示例,说明了这个问题,并展示了使用绑定标记的解决方案:

https://stackoverflow.com/a/3513906/7432

好的,我似乎已经解决了我的问题,但不是在我原来打算的方式。为了查看输入的字符,我在通过.bind()传递给函数的事件参数上使用了.char。这允许我看到字符,但如果不将.get()收集的字符串和.char收集的字符串连接起来,我仍然无法看到完整的字符串。这是有效的,但是它看起来不太好,似乎不属于Python,所以我仍然愿意得到更干净、更有效的答案。

def keyPress(event): ##Argument is because bind passes the event to the function
    collectedString = (entryBox.get() + event.char)
    print(collectedString)

最新更新