Python 3.x 为什么用户操作无法访问tkinter条目小部件

Python 3.x 为什么用户操作无法访问tkinter条目小部件,python-3.x,tkinter,tkinter-entry,Python 3.x,Tkinter,Tkinter Entry,是一个类似的问题,所以我认为我在正确的论坛。我有一个tkinter应用程序,它可以计算某些东西的“步数”。在大约20亿+1个加法(接近最大32位整数的大小)之后,条目小部件中显示的计数不再是用户可访问的——无法将光标聚焦在显示的值中,也无法选择该值的部分或全部字符。如果我重新启动应用程序,并在启动前将计数预设为199999999(“更新”),则仍然需要20亿步或更多的步骤才能显示此问题。下面是一个精简的应用程序,它在64位Windows 10和Raspberry Pi 4上显示了这个问题。(原始

是一个类似的问题,所以我认为我在正确的论坛。我有一个tkinter应用程序,它可以计算某些东西的“步数”。在大约20亿+1个加法(接近最大32位整数的大小)之后,条目小部件中显示的计数不再是用户可访问的——无法将光标聚焦在显示的值中,也无法选择该值的部分或全部字符。如果我重新启动应用程序,并在启动前将计数预设为199999999(“更新”),则仍然需要20亿步或更多的步骤才能显示此问题。下面是一个精简的应用程序,它在64位Windows 10和Raspberry Pi 4上显示了这个问题。(原始脚本已被替换。请参见注释。2021年1月17日)

到目前为止,在我更大的应用程序中,当这个问题发生时,用户将无法访问所有条目小部件。
这是一个已知的tkinter问题吗?有什么简单的解决方法吗?

我猜问题在于,您在空闲后使用
的方式使得
mainloop
无法正确服务事件。实际上,idle循环永远不会变为空,因为对于您启动的每个idle事件,您都会重新添加一个。因为tkinter忙于处理“空闲”事件,所以它很难处理其他事件,比如按钮和鼠标点击


每次计数之间至少应有毫秒或更长的延迟,以便tkinter事件处理系统有机会处理除空闲事件之外的其他事件。

我知道我不应该回答我自己的问题,但我认为我现在得到的答案可能对看到此问题的其他人很重要。在询问之前,我在这里和其他地方做了不少研究。如果我找到了答案,我就不会打扰社区了。问题只是确认是否有其他人看到过这个问题。我没有收到任何“是”或“否”的评论或回答。相反,问题被倒计时。一个人在提问前如何展示所做的研究?我认为问题很清楚。答案对我来说当然很重要

我还问,是否有任何简单的解决方法,可以用来克服这个问题。好了,开始吧。在Windows上,以下脚本仍然显示异常显示行为,但至少该脚本仍然有效,允许在计数期间复制输入值,并且不会延迟工作(countUp)

from tkinter import *  #python3

start = False
count = 0

def startCount():
    global start
    start = True
    countUp()

def stopCount():
    global start
    start = False
    eVal.set(count)

def get_eVal():
    global count
    count = int(eVal.get())

def countUp():
    global count, start
    count += 1
    if count % 1000 == 0:
        eVal.set(count)
    if start:
        root.update_idletasks()
        root.after(0, countUp)

root = Tk()
eVal = StringVar()
frame = Frame(root)
on = Button(frame, text='Start', command=startCount)
off = Button(frame, text='Stop', command=stopCount)
updt = Button(frame, text='Update', command=get_eVal)
entry = Entry(frame, textvariable=eVal, width=20, justify=RIGHT)
on.pack(side=LEFT)
off.pack(side=LEFT, padx=(8,4), pady=6)
updt.pack(side=LEFT, padx=(4,8))
entry.pack(side=LEFT)
frame.pack()
root.mainloop()
反常的行为是,你的桌面可以显示两个闪烁的光标(很抱歉,此图像中的竖条没有闪烁),即使应用程序没有焦点,条目中的选择也会持续。但是,脚本仍然可以运行

我现在正在测试第二个脚本,它敢于使用.update。我将在稍后评论这是否是一个有效的解决办法

from tkinter import *   # python3

start = False
count = 0
quit = False

def startCount():
    global start
    start = True

def stopCount():
    global start
    start = False
    eVal.set(count)

def get_eVal():
    global count
    count = int(eVal.get())

def countUp():
    global count
    count += 1
    if count % 1000 == 0:
        eVal.set(count)

root = Tk()
eVal = StringVar()
frame = Frame(root)
on = Button(frame, text='Start', command=startCount)
off = Button(frame, text='Stop', command=stopCount)
updt = Button(frame, text='Update', command=get_eVal)
entry = Entry(frame, textvariable=eVal, width=20, justify=RIGHT)
on.pack(side=LEFT)
off.pack(side=LEFT, padx=(8,4), pady=6)
updt.pack(side=LEFT, padx=(4,8))
entry.pack(side=LEFT)
frame.pack()
while quit == False:
    if start:
        countUp()
    try:
        root.update_idletasks()
        root.update()
    except:
        break

我无法运行您的示例,我得到一个错误,表明eVal未定义。可能是因为eVal是在main中定义的,但函数startCount、stopCount、get_eVal等不能全局使用,所以我在运行此脚本时没有遇到这个问题,但无论如何,请尝试通过quit=False语句向上移动eVal=StringVal()语句,并根据需要添加global。你使用什么python3/系统?顺便说一句,我认为if name='main':的作用域是全局的。不,仔细想想,不要将eVal=StringVal()语句移到root=TK()之前。很抱歉,我不知道您的问题是什么。您是否尝试在结束时删除
循环?使用自己的循环并调用
update
远不如让
mainloop
完成它的工作那么有效,而且实际上可能会导致问题。这不是tkinter的使用方式。我编辑了脚本以避免。更新,但是如果我单击条目的显示,此版本很容易出现“无响应”。如果没有任何答案,我认为答案是“不,这不是已知的tkinter问题”。mainloop()特别是,这似乎不是一个容易解决的问题。谢谢,但我认为这会将最短测试时间(更不用说在1毫秒内完成的工作)延长到23天。当出现此问题时,我无法使用复制条目值。更新我的旧方法,但至少脚本仍然执行。当我有时间时,我肯定会尝试各种变体。如果你如果你想分享你的研究成果,那么你应该勾选“回答你自己的问题——分享你的知识,问答式”,然后回答。你的问题是“有什么简单的解决方法吗?”而不是“这个问题只是为了确认是否有人见过这个问题。”。“。您阅读的是什么stackoverflow说明手册?我想知道所有的海关和要求。是的,我打了两个问题。你关注的那个问题,“这是一个已知的tkinter问题吗?”一个直截了当的回答是肯定的还是否定的。我的目的是得到确认。还没有发生。但是谢谢。这不是来自任何说明手册,当在最底部询问有关stackoverflow的问题时,如果这是一篇问答风格的帖子,将会有一个复选按钮来切换。我只是指出“我知道我不应该回答我自己的问题”是错误的。如果您在发布问题后给出了答案,您可以回答自己的问题。尽管如此,我认为我误解了你的回答,认为你在发布问题时知道答案。为误解道歉。如果你想通读一个好问题,可能会有帮助。第二个脚本不是解决办法。结果表明,最初提出的问题是相同的。这可能太晚了,但我想向我冒犯的所有成员道歉,特别是那些提供了优秀代码和项目保存答案的成员,比如
from tkinter import *   # python3

start = False
count = 0
quit = False

def startCount():
    global start
    start = True

def stopCount():
    global start
    start = False
    eVal.set(count)

def get_eVal():
    global count
    count = int(eVal.get())

def countUp():
    global count
    count += 1
    if count % 1000 == 0:
        eVal.set(count)

root = Tk()
eVal = StringVar()
frame = Frame(root)
on = Button(frame, text='Start', command=startCount)
off = Button(frame, text='Stop', command=stopCount)
updt = Button(frame, text='Update', command=get_eVal)
entry = Entry(frame, textvariable=eVal, width=20, justify=RIGHT)
on.pack(side=LEFT)
off.pack(side=LEFT, padx=(8,4), pady=6)
updt.pack(side=LEFT, padx=(4,8))
entry.pack(side=LEFT)
frame.pack()
while quit == False:
    if start:
        countUp()
    try:
        root.update_idletasks()
        root.update()
    except:
        break