Robin Dunn wrote:
Larry Bates wrote:
Robin Dunn wrote:
Larry Bates wrote:
Thoughts?
Do the other code in a thread, and make the callback use wx.CallAfter or post an event so the update of the progress dialog can be done in the gui thread. If the cancel button was pressed then set a flag that the download thread will check periodically so it knows to stop (or send the message in some other thread-safe way).
Real newbie here. It sounds like this would be the best way:
> or post an event so the update of the progress dialog can be done in
> the gui thread.
I "really" tried on this one, but it exhibits the same behavior. Can't ever click on the Cancel button. See sample code below.
Thanks for all your help.
You still are not calling the app's MainLoop method. And you seem to have missed the "Do the other code in a thread" part of my comment.
>>> Do the other code in a thread, and make the callback use wx.CallAfter
>>> or post an event so the update of the progress dialog can be done in
>>> the gui thread.
Sorry, I read your instructions as "Do in a thread and make callback or post
an event..." Note the OR.
I tried running my other code in a separate thread, but Python DAVLIB refuses run in a separate thread and I'm not up to a complete rewrite of that code at the present.
I tried running the MainLoop in another thread, but it makes no difference.
import wx
import time
myEVT_UPDATE_PROGRESS = wx.NewEventType()
EVT_UPDATE_PROGRESS = wx.PyEventBinder(myEVT_UPDATE_PROGRESS, 1)
class MyProgressEvent(wx.PyCommandEvent):
def __init(self, evtType, id):
wxPYcommendEvent.__init(self, evType, id)
self.myVal=None
def SetVal(self, val):
self.myVal=val
def GetVal(self):
return self.myVal
class GUIprogressCallback(object):
def __init__(self, parent):
self.uploadTotal=0
self.uploadPosition=0
···
#
# Bind my custom event that gets posted by caller to update the progress
#
parent.Bind(EVT_UPDATE_PROGRESS, self.update)
def setUploadTotal(self, uploadTotal):
'''
setUploadTotal - if user is doing a mult-file upload and would like to
set the total upload size for all files, use this
method. Otherwise we will assume a single-file upload
and the total will be the size of the file being
uploaded.
'''
self.uploadTotal=uploadTotal
def start(self, fileName, fileSize):
'''
start - This method is called to start the upload of a file
'''
#
# Truncate the fileName if it is too long to display
#
if len(fileName) > 90:
fileName=".."+fileName[-90:]
#
# Create the dialog unless I've already created it (e.g. previous file
# in a multi-file upload).
#
if not hasattr(self, 'dlg'):
self._createDialog(msg=fileName, maximum=self.uploadTotal)
#
# Handle the possibility that files changed sizes between the time that
# I calculated uploadTotal and when I actually get to uploading them by
# backing down from uploadTotal, but can't be less than 0.
#
if self.uploadPosition+fileSize > self.uploadTotal:
self.uploadPosition=max(self.uploadTotal-fileSize, 0)
#
# Update the dialog with the info
#
self.dlg.Update(self.uploadPosition, newmsg=fileName)
return True
def update(self, event):
'''
update - Events are posted as file upload is progressing. This method
is bound so it picks up those events (every block). We
calculate the percentage complete and update the progessDialog
with this information and update the progress gauge.
'''
filePosition=event.GetVal()
#
# Handle both single- and mult-file upload percentage complete.
#
uploadPosition=self.uploadPosition+filePosition
#
# Calculate and display the percent complete and update the position
# of the progress dialog gauge.
#
percentstr=int(100.0*float(uploadPosition)/float(self.uploadTotal))
msg="WebSafe Upload-%s%%" % percentstr
self.dlg.SetLabel(msg)
wx.Yield()
keepgoing, skip=self.dlg.Update(uploadPosition)
#
# See if user clicked the cancel button
#
if not keepgoing:
self.close()
return True
def _createDialog(self, msg='', maximum=100):
#
# Create progress dialog and display it, but it must run in a different
# thread or user won't be able to click cancel button.
#
self.dlg=wx.ProgressDialog(title="WebSafe Upload",
message="",
maximum=maximum,
style=wx.PD_APP_MODAL |
#wx.PD_AUTO_HIDE | \
wx.PD_CAN_ABORT | \
wx.PD_REMAINING_TIME)
self.dlg.SetDimensions(-1, -1, width=500, height=-1,
sizeFlags=wx.SIZE_AUTO_HEIGHT)
self.dlg.Show(True)
def complete(self, fileSize):
self.uploadPosition=self.uploadPosition+fileSize
return True
def close(self):
self.isRunning=False
self.dlg.Destroy()
return False
class MyApp(wx.PySimpleApp):
def OnInit(self):
wx.InitAllImageHandlers(0)
return True
if __name__ == "__main__":
import time
import thread
app=wx.PySimpleApp(0)
wx.InitAllImageHandlers()
thread.start_new_thread(app.MainLoop, ())
evt=MyProgressEvent(myEVT_UPDATE_PROGRESS, -1)
blockSize=1<<16
#
# Test multi-file upload
#
fileNames=['filename1.txt', 'filename2.txt', 'filename3.txt']
fileSizes=[(1<<20), 2*(1<<20), 3*(1<<20)]
CB=GUIprogressCallback(app)
CB.setUploadTotal(sum(fileSizes))
for fileName, fileSize in zip(fileNames, fileSizes):
CB.start(fileName, fileSize)
for i in xrange(blockSize, fileSize, blockSize):
evt.SetVal(i)
app.ProcessEvent(evt)
time.sleep(0.5)
CB.complete(fileSize)
CB.close()