打开一个进度条直到函数任务结束
Open a progress bar until function task ends
我在左侧有一个事件侦听器,双击 wx.Grid 打开一个对话框以确认更改。如果用户单击 "Yes",我将调用一个需要大约 6 秒执行的函数,同时 window 冻结。我想做的是打开一个进度条,这样用户就可以等到函数完成它的任务,或者更好的是,在对话框中有进度条。
我不知道从哪里开始,因为直到现在我才需要进度条。
我看过的很多解决方案都建议使用线程,但我对 Python 中的线程非常缺乏经验。
我希望有人能够帮助我显示使用 wxPython 的 运行 任务的进度。
到目前为止,这是我的代码:
def OnCellLeftDClick(self, evt):
if evt.GetCol() == 17:
dlg = wx.MessageDialog(None, "Do you want to change " + self.GetCellValue(evt.GetRow(), 1) + " bid?",'Updater',wx.YES_NO | wx.ICON_QUESTION)
result = dlg.ShowModal()
if result == wx.ID_YES:
from chanbeBid import changeBidTb
changeBidTb(self.GetCellValue(evt.GetRow(), 1), self.GetCellValue(evt.GetRow(), 16))
evt.Skip()
谢谢,
您可以使用_thread 模块来创建新的线程和pubsub 来处理线程之间的通信。一种方法如下所示。我在代码中添加了一些注释。
import wx
import time
import _thread
from pubsub import pub
seconds = 10
class MyFrame(wx.Frame):
def __init__(self):
"""
Just a button to start counting
"""
super().__init__(None, title='Counting until...')
self.panel = wx.Panel(self)
self.button = wx.Button(self.panel, label='Count', pos=(50, 50))
self.button.Bind(wx.EVT_BUTTON, self.OnCount)
## This will subscribe the window to the message 'Finish counting'.
## Thus, everytime the message is broadcast the self.Pass method
## will be executed.
pub.subscribe(self.Pass, 'Finish counting')
def OnCount(self, event):
dlg = wx.MessageDialog(None, "Do you want to count?",
style=wx.YES_NO|wx.ICON_QUESTION)
if dlg.ShowModal() == wx.ID_YES:
self.count()
else:
pass
def count(self):
## Creates and starts a new thread that will execute the self.wait
## method. Notice that the thread is started before the ProgressDialog
## because the ProgressDialog will keep the main thread busy
_thread.start_new_thread(self.wait, (seconds,))
## ProgressDialog that will keep running until maxV is reached or
## until self.keepGoing is set to False
maxV = 100
dlg = wx.ProgressDialog("Progress dialog example",
"An informative message",
maximum = maxV,
parent=self,
style = 0
| wx.PD_APP_MODAL
#| wx.PD_CAN_ABORT
#| wx.PD_CAN_SKIP
| wx.PD_ELAPSED_TIME
#| wx.PD_ESTIMATED_TIME
#| wx.PD_REMAINING_TIME
#| wx.PD_AUTO_HIDE
)
self.keepGoing = True
count = 0
while self.keepGoing and count < maxV:
count += 1
wx.MilliSleep(250)
wx.SafeYield()
(keepGoing, skip) = dlg.Update(count)
dlg.Destroy()
def wait(self, secs):
## This is the function that is executed by the new thread
## when it finishs the wx.CallAfter method broadcast the message
## 'Finish counting' that triggers self.Pass as mentioned above.
time.sleep(secs)
wx.CallAfter(pub.sendMessage, 'Finish counting')
def Pass(self):
## Changes self.keepGoing to false so the ProgressDialog is destroyed.
self.keepGoing = False
if __name__ == "__main__":
app = wx.App()
frame = MyFrame()
frame.Show()
app.MainLoop()
关于对话框中的进度条 window 要求继续。这可以完成,但您需要构建自定义对话框 window 并且可能使用 wx.Gauge
而不是 wx.ProgressDialog
。此外,您很可能希望此自定义 window 是模态的(冻结程序中的所有其他 windows,因此用户必须等待线程中的函数 运行 完成)。为此,将以下方法添加到自定义对话框 class、
def ShowModal(self):
"""
wx.Dialog behavior
"""
self._disabler = wx.WindowDisabler(self)
self.Show()
self.eventLoop = wx.GUIEventLoop()
self.eventLoop.Run()
并以与正常方式相同的方式显示自定义对话框 wx.Dialog
、custom_dialog.ShowModal()
我在左侧有一个事件侦听器,双击 wx.Grid 打开一个对话框以确认更改。如果用户单击 "Yes",我将调用一个需要大约 6 秒执行的函数,同时 window 冻结。我想做的是打开一个进度条,这样用户就可以等到函数完成它的任务,或者更好的是,在对话框中有进度条。
我不知道从哪里开始,因为直到现在我才需要进度条。
我看过的很多解决方案都建议使用线程,但我对 Python 中的线程非常缺乏经验。
我希望有人能够帮助我显示使用 wxPython 的 运行 任务的进度。
到目前为止,这是我的代码:
def OnCellLeftDClick(self, evt):
if evt.GetCol() == 17:
dlg = wx.MessageDialog(None, "Do you want to change " + self.GetCellValue(evt.GetRow(), 1) + " bid?",'Updater',wx.YES_NO | wx.ICON_QUESTION)
result = dlg.ShowModal()
if result == wx.ID_YES:
from chanbeBid import changeBidTb
changeBidTb(self.GetCellValue(evt.GetRow(), 1), self.GetCellValue(evt.GetRow(), 16))
evt.Skip()
谢谢,
您可以使用_thread 模块来创建新的线程和pubsub 来处理线程之间的通信。一种方法如下所示。我在代码中添加了一些注释。
import wx
import time
import _thread
from pubsub import pub
seconds = 10
class MyFrame(wx.Frame):
def __init__(self):
"""
Just a button to start counting
"""
super().__init__(None, title='Counting until...')
self.panel = wx.Panel(self)
self.button = wx.Button(self.panel, label='Count', pos=(50, 50))
self.button.Bind(wx.EVT_BUTTON, self.OnCount)
## This will subscribe the window to the message 'Finish counting'.
## Thus, everytime the message is broadcast the self.Pass method
## will be executed.
pub.subscribe(self.Pass, 'Finish counting')
def OnCount(self, event):
dlg = wx.MessageDialog(None, "Do you want to count?",
style=wx.YES_NO|wx.ICON_QUESTION)
if dlg.ShowModal() == wx.ID_YES:
self.count()
else:
pass
def count(self):
## Creates and starts a new thread that will execute the self.wait
## method. Notice that the thread is started before the ProgressDialog
## because the ProgressDialog will keep the main thread busy
_thread.start_new_thread(self.wait, (seconds,))
## ProgressDialog that will keep running until maxV is reached or
## until self.keepGoing is set to False
maxV = 100
dlg = wx.ProgressDialog("Progress dialog example",
"An informative message",
maximum = maxV,
parent=self,
style = 0
| wx.PD_APP_MODAL
#| wx.PD_CAN_ABORT
#| wx.PD_CAN_SKIP
| wx.PD_ELAPSED_TIME
#| wx.PD_ESTIMATED_TIME
#| wx.PD_REMAINING_TIME
#| wx.PD_AUTO_HIDE
)
self.keepGoing = True
count = 0
while self.keepGoing and count < maxV:
count += 1
wx.MilliSleep(250)
wx.SafeYield()
(keepGoing, skip) = dlg.Update(count)
dlg.Destroy()
def wait(self, secs):
## This is the function that is executed by the new thread
## when it finishs the wx.CallAfter method broadcast the message
## 'Finish counting' that triggers self.Pass as mentioned above.
time.sleep(secs)
wx.CallAfter(pub.sendMessage, 'Finish counting')
def Pass(self):
## Changes self.keepGoing to false so the ProgressDialog is destroyed.
self.keepGoing = False
if __name__ == "__main__":
app = wx.App()
frame = MyFrame()
frame.Show()
app.MainLoop()
关于对话框中的进度条 window 要求继续。这可以完成,但您需要构建自定义对话框 window 并且可能使用 wx.Gauge
而不是 wx.ProgressDialog
。此外,您很可能希望此自定义 window 是模态的(冻结程序中的所有其他 windows,因此用户必须等待线程中的函数 运行 完成)。为此,将以下方法添加到自定义对话框 class、
def ShowModal(self):
"""
wx.Dialog behavior
"""
self._disabler = wx.WindowDisabler(self)
self.Show()
self.eventLoop = wx.GUIEventLoop()
self.eventLoop.Run()
并以与正常方式相同的方式显示自定义对话框 wx.Dialog
、custom_dialog.ShowModal()