]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/throbber.py
2 A throbber displays an animated image that can be
3 started, stopped, reversed, etc. Useful for showing
4 an ongoing process (like most web browsers use) or
5 simply for adding eye-candy to an application.
7 Throbbers utilize a wxTimer so that normal processing
8 can continue unencumbered.
12 # throbber.py - Cliff Wells <clifford.wells@comcast.net>
14 # Thanks to Harald Massa <harald.massa@suedvers.de> for
15 # suggestions and sample code.
19 # 12/12/2003 - Jeff Grimmett (grimmtooth@softhome.net)
21 # o 2.5 compatability update.
28 # ------------------------------------------------------------------------------
30 THROBBER_EVENT
= wx
.NewEventType()
31 EVT_UPDATE_THROBBER
= wx
.PyEventBinder(THROBBER_EVENT
, 0)
33 class UpdateThrobberEvent(wx
.PyEvent
):
35 wx
.PyEvent
.__init
__(self
)
36 self
.SetEventType(THROBBER_EVENT
)
38 # ------------------------------------------------------------------------------
40 class Throbber(wx
.PyPanel
):
42 The first argument is either the name of a file that will be split into frames
43 (a composite image) or a list of strings of image names that will be treated
44 as individual frames. If a single (composite) image is given, then additional
45 information must be provided: the number of frames in the image and the width
46 of each frame. The first frame is treated as the "at rest" frame (it is not
47 shown during animation, but only when Throbber.Rest() is called.
48 A second, single image may be optionally specified to overlay on top of the
49 animation. A label may also be specified to show on top of the animation.
51 def __init__(self
, parent
, id,
52 bitmap
, # single (composite) bitmap or list of bitmaps
53 pos
= wx
.DefaultPosition
,
54 size
= wx
.DefaultSize
,
55 frameDelay
= 0.1,# time between frames
56 frames
= 0, # number of frames (only necessary for composite image)
57 frameWidth
= 0, # width of each frame (only necessary for composite image)
58 label
= None, # optional text to be displayed
59 overlay
= None, # optional image to overlay on animation
60 reverse
= 0, # reverse direction at end of animation
61 style
= 0, # window style
63 wx
.PyPanel
.__init
__(self
, parent
, id, pos
, size
, style
, name
)
66 self
.running
= (1 != 1)
67 _seqTypes
= (type([]), type(()))
69 # set size, guessing if necessary
72 if type(bitmap
) in _seqTypes
:
73 width
= bitmap
[0].GetWidth()
78 if type(bitmap
) in _seqTypes
:
79 height
= bitmap
[0].GetHeight()
81 height
= bitmap
.GetHeight()
82 self
.width
, self
.height
= width
, height
85 assert width
!= -1 and height
!= -1, "Unable to guess size"
88 extentX
, extentY
= self
.GetTextExtent(label
)
89 self
.labelX
= (width
- extentX
)/2
90 self
.labelY
= (height
- extentY
)/2
91 self
.frameDelay
= frameDelay
94 self
.autoReverse
= reverse
95 self
.overlay
= overlay
96 if overlay
is not None:
97 self
.overlay
= overlay
98 self
.overlayX
= (width
- self
.overlay
.GetWidth()) / 2
99 self
.overlayY
= (height
- self
.overlay
.GetHeight()) / 2
100 self
.showOverlay
= overlay
is not None
101 self
.showLabel
= label
is not None
103 # do we have a sequence of images?
104 if type(bitmap
) in _seqTypes
:
105 self
.submaps
= bitmap
106 self
.frames
= len(self
.submaps
)
107 # or a composite image that needs to be split?
111 for chunk
in range(frames
):
112 rect
= (chunk
* frameWidth
, 0, width
, height
)
113 self
.submaps
.append(bitmap
.GetSubBitmap(rect
))
115 # self.sequence can be changed, but it's not recommended doing it
116 # while the throbber is running. self.sequence[0] should always
117 # refer to whatever frame is to be shown when 'resting' and be sure
118 # that no item in self.sequence >= self.frames or < 0!!!
119 self
.sequence
= range(self
.frames
)
121 self
.SetClientSize((width
, height
))
124 self
.timer
= wx
.Timer(self
, timerID
)
126 self
.Bind(EVT_UPDATE_THROBBER
, self
.Rotate
)
127 self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
)
128 self
.Bind(wx
.EVT_TIMER
, self
.OnTimer
, self
.timer
)
129 self
.Bind(wx
.EVT_WINDOW_DESTROY
, self
.OnDestroyWindow
)
132 def DoGetBestSize(self
):
133 return (self
.width
, self
.height
)
136 def OnTimer(self
, event
):
137 wx
.PostEvent(self
, UpdateThrobberEvent())
140 def OnDestroyWindow(self
, event
):
146 dc
.DrawBitmap(self
.submaps
[self
.sequence
[self
.current
]], 0, 0, True)
147 if self
.overlay
and self
.showOverlay
:
148 dc
.DrawBitmap(self
.overlay
, self
.overlayX
, self
.overlayY
, True)
149 if self
.label
and self
.showLabel
:
150 dc
.DrawText(self
.label
, self
.labelX
, self
.labelY
)
151 dc
.SetTextForeground(wx
.WHITE
)
152 dc
.DrawText(self
.label
, self
.labelX
-1, self
.labelY
-1)
155 def OnPaint(self
, event
):
156 self
.Draw(wx
.PaintDC(self
))
160 def Rotate(self
, event
):
161 self
.current
+= self
.direction
162 if self
.current
>= len(self
.sequence
):
165 self
.current
= len(self
.sequence
) - 1
173 self
.current
= len(self
.sequence
) - 1
174 self
.Draw(wx
.ClientDC(self
))
177 # --------- public methods ---------
178 def SetFont(self
, font
):
179 """Set the font for the label"""
180 wx
.Panel
.SetFont(self
, font
)
181 self
.SetLabel(self
.label
)
182 self
.Draw(wx
.ClientDC(self
))
186 """Stop the animation and return to frame 0"""
189 self
.Draw(wx
.ClientDC(self
))
193 """Change the direction of the animation"""
194 self
.direction
= -self
.direction
198 """Returns True if the animation is running"""
203 """Start the animation"""
205 self
.running
= not self
.running
206 self
.timer
.Start(int(self
.frameDelay
* 1000))
210 """Stop the animation"""
213 self
.running
= not self
.running
216 def SetFrameDelay(self
, frameDelay
= 0.05):
217 """Delay between each frame"""
218 self
.frameDelay
= frameDelay
224 def ToggleOverlay(self
, state
= None):
225 """Toggle the overlay image"""
227 self
.showOverlay
= not self
.showOverlay
229 self
.showOverlay
= state
230 self
.Draw(wx
.ClientDC(self
))
233 def ToggleLabel(self
, state
= None):
234 """Toggle the label"""
236 self
.showLabel
= not self
.showLabel
238 self
.showLabel
= state
239 self
.Draw(wx
.ClientDC(self
))
242 def SetLabel(self
, label
):
243 """Change the text of the label"""
246 extentX
, extentY
= self
.GetTextExtent(label
)
247 self
.labelX
= (self
.width
- extentX
)/2
248 self
.labelY
= (self
.height
- extentY
)/2
249 self
.Draw(wx
.ClientDC(self
))
253 # ------------------------------------------------------------------------------