我有一个大程序,其中一个部分包括单击按钮(这个GUI是用wxPython制作的)。基本上,按钮是一个计时器,当你点击它时,按钮的文本会根据剩余的时间进行切换,例如5秒、4秒、3秒。。。但是,由于某些原因,当我点击GUI中的按钮时,整个程序冻结,我不得不强制退出应用程序。(在我点击这个按钮之前,应用程序中的所有其他功能都很好,并且会做出响应)。下面是单击按钮时调用的事件处理程序。在
提前谢谢!在
def TossUpTimer(self, event):
while self.tossuptimer > -1:
while self.tossuptimer > 0:
self.tossupbutton.SetLabel(str(self.tossuptimer) + "Seconds")
time.sleep(1)
self.tossuptimer -= 1
if self.tossuptimer == 0:
self.tossupbutton.SetLabel("Time is Up!")
time.sleep(1)
self.tossupbutton.SetLabel(str(self.tossuptimer) + "Seconds")
self.tossuptimer = 5
Why your GUI app freezes试图解释基本思想,以及处理它的所有不同选项。在
但这里有一个简短的版本:
GUI应用程序的全部意义在于它运行一个事件循环,对来自用户或操作系统的事件做出响应。为特定事件编写处理程序。在下一个事件处理程序之前,GUI不能返回。这意味着整个应用程序都被冻结了。在
您需要尽快从处理程序返回。你永远不能做的是
time.sleep(1)
或一个长的while
循环或直接在处理程序中的任何类型的操作。在有很多方法可以解决这个问题。两种最常见的方法是请求事件循环稍后运行某些代码,或者将其移到后台线程。(
wx
添加了第三种方法,SafeYield
和朋友,这在某些情况下是合适的,但可能不是您在这里想要的。)对于第一个替代方案,我们的想法是,不是围绕
sleep
循环,而是编写一个处理循环的单个迭代的函数,并安排一个计时器以每秒触发一次该函数。这被称为“把你的控制流从里到外”,这可能有点难以让你的头脑清醒过来。在不幸的是,我不能百分之百地确定你要做什么,因为正如Jon Clements指出的,你的逻辑即使在顺序程序中也没有意义。但我要写一些简单的东西:当你点击按钮时,它会倒计时一次/秒,持续5秒,然后停止计数。在
有关详细信息,请参见Using wx.Timers和^{} 文档。在
线程版本在某些方面更简单,在其他方面更复杂。您可以不使用序列逻辑,但除了通过调用
^{pr2}$PostEvent
间接地与任何GUI小部件对话。所以:如果你做了很多这样的事情,你可能想写更多通用的“on main thread”函数,而不是为每个函数编写所有这些样板文件。(事实上,您可以编写一个完整的泛型函数,
wxPython
确实应该附带该函数,但实际上没有。)相关问题 更多 >
编程相关推荐