Welcome, guest | Sign In | My Account | Store | Cart

I come across some cases, where I need to hook a progress bar from WX to my current running python project/script to indicate the current process progress. Some how if you use MainLoop() in child thread will cause the WX session hang and EVT handle will failed. After some study, found that WXAPP class instance and MainLoop have to same namespace. I manage to redesign it and make it work now. Just mail/vote me, if you feel this is useful for your project. E-Mail : cheengshuchin@gmail.com

Python, 97 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import psyco
psyco.full()
#import win32traceutil
import sys
try:
	sys.setdefaultencoding('dbcs')
except:
	print 'encoding dbcs error!'
import os
if sys.platform == "win32":
	import msvcrt
	try:
		msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
	except:
		print 'Native std error!'
import gc
import threading
import wx
import gettext

class wxpbr(wx.App):
    def __init__(self,parent,*arg,**kwd):
        wx.App.__init__(self,redirect=0,*arg,**kwd)
        self.parent=parent
        self.title=self.parent.title
        self.text=self.parent.text
        self.max=self.parent.max
        self.style=self.parent.style
        self.count=self.parent.count
        self.status=self.parent.status
        self.dlg=0
    def OnInit(self):
        wx.InitAllImageHandlers()
        self.cscpbr=wx.Frame(None, -1, "")
        self.SetTopWindow(self.cscpbr)
        self.Bind(wx.EVT_TIMER, self.pbrm)
        self.t1 = wx.Timer(self.cscpbr)
        self.t1.Start(1)
        return 1
    def pbrm(self, evt):
        if self.dlg:
            if self.text<>self.parent.text or self.count<>self.parent.count:
                self.text=self.parent.text
                self.count=self.parent.count
                self.parent.status=self.status=self.dlg.Update(self.count,self.text)
        else:
            self.dlg = wx.ProgressDialog(self.title,self.text,self.max,self.cscpbr,self.style)
            self.dlg.Bind(wx.EVT_CLOSE, self.close)
        if self.count>=self.max:
            self.parent.status=self.status=True
            self.close(None)
        elif self.parent.stop or (not self.status):
            self.parent.status=self.status=False
            self.close(None)
    def close(self,evt):
        self.parent.stop=1
        self.dlg.Destroy()
        self.cscpbr.Close(True)
class pbr(threading.Thread,object):
    def __init__(self,title,text,max,style,*arg,**kwd):
        threading.Thread.__init__(self,*arg,**kwd)
        self.arg=arg
        self.kwd=kwd
        self.title=title
        self.text=text
        self.max=max
        self.style=style
        self.count=0
        self.status=True
        self.stop=0
        #self.pb=wxpbr(self.title,self.text,self.max,self.style,*self.arg,**self.kwd)
    def run(self):
        self.pb=wxpbr(self,*self.arg,**self.kwd)
        self.pb.MainLoop()
    def close(self):
        self.stop=1
def pbar(title="Progress dialog example",
        text="An informative message",
        max=100,
        style=wx.PD_CAN_ABORT|wx.PD_AUTO_HIDE|wx.PD_SMOOTH|wx.PD_ELAPSED_TIME|wx.PD_ESTIMATED_TIME|wx.PD_REMAINING_TIME,
        *arg,**kwd):
    sys.setcheckinterval(0)
    gettext.install("wxpbr")
    app = pbr(title,text,max,style,*arg,**kwd)
    app.start()
    return app
def pbardemo():
    app=pbar()
    for x in range(0,app.max+1):
        app.count=x
        wx.MilliSleep(100)
        app.text="%s%%"%(x)
        if app.stop:
            break
    print app.status
if __name__ == "__main__":
    pbardemo()

This code seems work in windows, but I haven’t try it in Linux or Mac server. Hope someone can help me to verify on this. This code can modify and extend to use others dialog/WXAPP classes (e.g. TextBox, File/Directory Dialogs) as well. Please enjoy it. Please refer this as well: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/203471

1 comment

stewart midwinter 15 years, 7 months ago  # | flag

problems on Linux. I did test this under Ubuntu Linux. The recipe runs, but does create an exception on exiting, probably due to the way you close the app:

$ python pbardemo.py
True
Traceback (most recent call last):
  File "pbardemo.py", line 51, in pbrm
    self.close(None)
  File "pbardemo.py", line 57, in close
    self.dlg.Destroy()
  File "/usr/lib/python2.4/site-packages/wx-2.6-gtk2-unicode/wx/_core.py", line 13208, in __getattr__
    raise PyDeadObjectError(self.attrStr % self._name)
wx._core.PyDeadObjectError: The C++ part of the ProgressDialog object has been deleted, attribute access no longer allowed.
*** glibc detected *** corrupted double-linked list: 0x08171a60 ***
Aborted