我的 wxPython 小部件在激活另一个功能后冻结了我的程序
当我启动该程序时,它运行良好。但是,当我按下倒计时按钮,然后尝试激活操作按钮时,它冻结了。
import wx
import time
class LeftPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
self.text = parent.GetParent().rightPanel.text
self.text_2 = parent.GetParent().rightPanel.text_2
button1 = wx.Button(self, -1, 'Count', (10, 10))
button2 = wx.Button(self, -1, 'Countdown', (10, 60))
button3 = wx.Button(self, -1, 'Action', (10, 110))
self.Bind(wx.EVT_BUTTON, self.OnPlus, id=button1.GetId())
self.Bind(wx.EVT_BUTTON, self.OnMinus, id=button2.GetId())
self.Bind(wx.EVT_BUTTON, self.button_Pressed, id=button3.GetId())
self.timed_Out = 1
def OnPlus(self, event):
value = 1
for t in range(5000):
value = value + 1
time.sleep(1)
self.text.SetLabel(str(value))
def OnMinus(self, event):
import math
value = 60
for t in range(value):
value = value - 1
time.sleep(1)
self.text.SetLabel(str(value/60) + ':' + str(value%60))
self.timed_Out = 0
self.text_2.SetLabel(str('End o\'line.'))
def button_Pressed(self, event):
if self.timed_Out == 1:
if self.text_2 == 'First':
self.text_2.SetLabel('Second')
elif self.text_2 == 'Second':
self.text_2.SetLabel('First')
class RightPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
self.text = wx.StaticText(self, -1, '0', (10,60))
self.text_2 = wx.StaticText(self,-1,'First',(10, 120))
class Communicate(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600, 200))
panel = wx.Panel(self, -1)
self.rightPanel = RightPanel(panel, -1)
leftPanel = LeftPanel(panel, -1)
hbox = wx.BoxSizer()
hbox.Add(leftPanel, 1, wx.EXPAND | wx.ALL, 4)
hbox.Add(self.rightPanel, 1, wx.EXPAND | wx.ALL, 5)
panel.SetSizer(hbox)
self.Centre()
self.Show(True)
app = wx.App()
Communicate(None, -1, 'widgets communicate')
app.MainLoop()
When I start the program, it runs fine. But when I press the Countdown Button, and then attempt to activate the Action Button, it freezes.
import wx
import time
class LeftPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
self.text = parent.GetParent().rightPanel.text
self.text_2 = parent.GetParent().rightPanel.text_2
button1 = wx.Button(self, -1, 'Count', (10, 10))
button2 = wx.Button(self, -1, 'Countdown', (10, 60))
button3 = wx.Button(self, -1, 'Action', (10, 110))
self.Bind(wx.EVT_BUTTON, self.OnPlus, id=button1.GetId())
self.Bind(wx.EVT_BUTTON, self.OnMinus, id=button2.GetId())
self.Bind(wx.EVT_BUTTON, self.button_Pressed, id=button3.GetId())
self.timed_Out = 1
def OnPlus(self, event):
value = 1
for t in range(5000):
value = value + 1
time.sleep(1)
self.text.SetLabel(str(value))
def OnMinus(self, event):
import math
value = 60
for t in range(value):
value = value - 1
time.sleep(1)
self.text.SetLabel(str(value/60) + ':' + str(value%60))
self.timed_Out = 0
self.text_2.SetLabel(str('End o\'line.'))
def button_Pressed(self, event):
if self.timed_Out == 1:
if self.text_2 == 'First':
self.text_2.SetLabel('Second')
elif self.text_2 == 'Second':
self.text_2.SetLabel('First')
class RightPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
self.text = wx.StaticText(self, -1, '0', (10,60))
self.text_2 = wx.StaticText(self,-1,'First',(10, 120))
class Communicate(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600, 200))
panel = wx.Panel(self, -1)
self.rightPanel = RightPanel(panel, -1)
leftPanel = LeftPanel(panel, -1)
hbox = wx.BoxSizer()
hbox.Add(leftPanel, 1, wx.EXPAND | wx.ALL, 4)
hbox.Add(self.rightPanel, 1, wx.EXPAND | wx.ALL, 5)
panel.SetSizer(hbox)
self.Centre()
self.Show(True)
app = wx.App()
Communicate(None, -1, 'widgets communicate')
app.MainLoop()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是因为您将
time.sleep
调用放入按钮事件处理函数中。这将导致用户界面冻结。随着计数器标签的更新,它可能会在视觉上得到更新(这不适合我),但在事件处理程序完成之前,任何界面元素都不会工作。您需要做的是在单独的线程中运行计时器;然后,每秒向主窗口发送一个事件,告诉它更新其计数器。您可以使用
wx.PostEvent
函数来做到这一点。或者,为了获得更简单、更好的解决方案,您可以使用为此目的构建的
wx.Timer
。 这里有一个关于它的教程。您也可以使用它来重复事件,这就是倒计时的情况。有一个关于通过 UI 事件激活长时间运行的任务的更通用教程;我放置此链接是因为我猜测 Google 上的人们在搜索应用程序冻结原因时会寻找此链接,而且可能不是因为计时器。
That's because you are putting
time.sleep
calls in the button event handler function. This will cause the user interface to freeze. It may get visually updated as the counter label gets updated (it doesn't for me) but no interface elements will work until the event handler finishes.What you need to do is to run the timer in a separate thread; then, each second, send an event to the main window to tell it to update its counter. You can do that with the
wx.PostEvent
function.Or, for a simpler and better solution, you can use
wx.Timer
built for this very purpose. Here is a tutorial about it. You can use it for repeating events too, which is the case for this countdown.There is a more generic tutorial about having long-running tasks activated by UI events; I am putting this link because I am guessing people on Google will be looking for this when they search for why their application is freezing, and it will probably not be because of a timer.