]>
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.
23 # ------------------------------------------------------------------------------
24 THROBBER_EVENT
= wx
.NewEventType()
25 def EVT_UPDATE_THROBBER(win
, func
):
26 win
.Connect(-1, -1, THROBBER_EVENT
, func
)
28 class UpdateThrobberEvent(wx
.PyEvent
):
30 wx
.PyEvent
.__init
__(self
)
31 self
.SetEventType(THROBBER_EVENT
)
33 # ------------------------------------------------------------------------------
35 class Throbber(wx
.Panel
):
37 The first argument is either the name of a file that will be split into frames
38 (a composite image) or a list of strings of image names that will be treated
39 as individual frames. If a single (composite) image is given, then additional
40 information must be provided: the number of frames in the image and the width
41 of each frame. The first frame is treated as the "at rest" frame (it is not
42 shown during animation, but only when Throbber.Rest() is called.
43 A second, single image may be optionally specified to overlay on top of the
44 animation. A label may also be specified to show on top of the animation.
46 def __init__(self
, parent
, id,
47 bitmap
, # single (composite) bitmap or list of bitmaps
48 pos
= wx
.DefaultPosition
,
49 size
= wx
.DefaultSize
,
50 frameDelay
= 0.1,# time between frames
51 frames
= 0, # number of frames (only necessary for composite image)
52 frameWidth
= 0, # width of each frame (only necessary for composite image)
53 label
= None, # optional text to be displayed
54 overlay
= None, # optional image to overlay on animation
55 reverse
= 0, # reverse direction at end of animation
56 style
= 0, # window style
58 wx
.Panel
.__init
__(self
, parent
, id, pos
, size
, style
, name
)
61 self
.running
= (1 != 1)
62 _seqTypes
= (type([]), type(()))
64 # set size, guessing if necessary
67 if type(bitmap
) in _seqTypes
:
68 width
= bitmap
[0].GetWidth()
73 if type(bitmap
) in _seqTypes
:
74 height
= bitmap
[0].GetHeight()
76 height
= bitmap
.GetHeight()
77 self
.width
, self
.height
= width
, height
80 assert width
!= -1 and height
!= -1, "Unable to guess size"
83 extentX
, extentY
= self
.GetTextExtent(label
)
84 self
.labelX
= (width
- extentX
)/2
85 self
.labelY
= (height
- extentY
)/2
86 self
.frameDelay
= frameDelay
89 self
.autoReverse
= reverse
90 self
.overlay
= overlay
91 if overlay
is not None:
92 self
.overlay
= overlay
93 self
.overlayX
= (width
- self
.overlay
.GetWidth()) / 2
94 self
.overlayY
= (height
- self
.overlay
.GetHeight()) / 2
95 self
.showOverlay
= overlay
is not None
96 self
.showLabel
= label
is not None
98 # do we have a sequence of images?
99 if type(bitmap
) in _seqTypes
:
100 self
.submaps
= bitmap
101 self
.frames
= len(self
.submaps
)
102 # or a composite image that needs to be split?
106 for chunk
in range(frames
):
107 rect
= (chunk
* frameWidth
, 0, width
, height
)
108 self
.submaps
.append(bitmap
.GetSubBitmap(rect
))
110 # self.sequence can be changed, but it's not recommended doing it
111 # while the throbber is running. self.sequence[0] should always
112 # refer to whatever frame is to be shown when 'resting' and be sure
113 # that no item in self.sequence >= self.frames or < 0!!!
114 self
.sequence
= range(self
.frames
)
116 self
.SetClientSize((width
, height
))
119 self
.timer
= wx
.Timer(self
, timerID
)
121 EVT_UPDATE_THROBBER(self
, self
.Rotate
)
122 wx
.EVT_PAINT(self
, self
.OnPaint
)
123 wx
.EVT_TIMER(self
, timerID
, self
.OnTimer
)
124 wx
.EVT_WINDOW_DESTROY(self
, self
.OnDestroyWindow
)
127 def OnTimer(self
, event
):
128 wx
.PostEvent(self
, UpdateThrobberEvent())
131 def OnDestroyWindow(self
, event
):
137 dc
.DrawBitmap(self
.submaps
[self
.sequence
[self
.current
]], 0, 0, True)
138 if self
.overlay
and self
.showOverlay
:
139 dc
.DrawBitmap(self
.overlay
, self
.overlayX
, self
.overlayY
, True)
140 if self
.label
and self
.showLabel
:
141 dc
.DrawText(self
.label
, self
.labelX
, self
.labelY
)
142 dc
.SetTextForeground(wx
.WHITE
)
143 dc
.DrawText(self
.label
, self
.labelX
-1, self
.labelY
-1)
146 def OnPaint(self
, event
):
147 self
.Draw(wx
.PaintDC(self
))
151 def Rotate(self
, event
):
152 self
.current
+= self
.direction
153 if self
.current
>= len(self
.sequence
):
156 self
.current
= len(self
.sequence
) - 1
164 self
.current
= len(self
.sequence
) - 1
165 self
.Draw(wx
.ClientDC(self
))
168 # --------- public methods ---------
169 def SetFont(self
, font
):
170 """Set the font for the label"""
171 wx
.Panel
.SetFont(self
, font
)
172 self
.SetLabel(self
.label
)
173 self
.Draw(wx
.ClientDC(self
))
177 """Stop the animation and return to frame 0"""
180 self
.Draw(wx
.ClientDC(self
))
184 """Change the direction of the animation"""
185 self
.direction
= -self
.direction
189 """Returns True if the animation is running"""
194 """Start the animation"""
196 self
.running
= not self
.running
197 self
.timer
.Start(self
.frameDelay
* 1000)
201 """Stop the animation"""
204 self
.running
= not self
.running
207 def SetFrameDelay(self
, frameDelay
= 0.05):
208 """Delay between each frame"""
209 self
.frameDelay
= frameDelay
215 def ToggleOverlay(self
, state
= None):
216 """Toggle the overlay image"""
218 self
.showOverlay
= not self
.showOverlay
220 self
.showOverlay
= state
221 self
.Draw(wx
.ClientDC(self
))
224 def ToggleLabel(self
, state
= None):
225 """Toggle the label"""
227 self
.showLabel
= not self
.showLabel
229 self
.showLabel
= state
230 self
.Draw(wx
.ClientDC(self
))
233 def SetLabel(self
, label
):
234 """Change the text of the label"""
237 extentX
, extentY
= self
.GetTextExtent(label
)
238 self
.labelX
= (self
.width
- extentX
)/2
239 self
.labelY
= (self
.height
- extentY
)/2
240 self
.Draw(wx
.ClientDC(self
))
244 # ------------------------------------------------------------------------------