]>
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 # ------------------------------------------------------------------------------
25 THROBBER_EVENT
= wx
.NewEventType()
26 def EVT_UPDATE_THROBBER(win
, func
):
27 win
.Connect(-1, -1, THROBBER_EVENT
, func
)
29 class UpdateThrobberEvent(wx
.PyEvent
):
31 wx
.PyEvent
.__init
__(self
)
32 self
.SetEventType(THROBBER_EVENT
)
34 # ------------------------------------------------------------------------------
36 class Throbber(wx
.Panel
):
38 The first argument is either the name of a file that will be split into frames
39 (a composite image) or a list of strings of image names that will be treated
40 as individual frames. If a single (composite) image is given, then additional
41 information must be provided: the number of frames in the image and the width
42 of each frame. The first frame is treated as the "at rest" frame (it is not
43 shown during animation, but only when Throbber.Rest() is called.
44 A second, single image may be optionally specified to overlay on top of the
45 animation. A label may also be specified to show on top of the animation.
47 def __init__(self
, parent
, id,
48 bitmap
, # single (composite) bitmap or list of bitmaps
49 pos
= wx
.DefaultPosition
,
50 size
= wx
.DefaultSize
,
51 frameDelay
= 0.1,# time between frames
52 frames
= 0, # number of frames (only necessary for composite image)
53 frameWidth
= 0, # width of each frame (only necessary for composite image)
54 label
= None, # optional text to be displayed
55 overlay
= None, # optional image to overlay on animation
56 reverse
= 0, # reverse direction at end of animation
57 style
= 0, # window style
59 wx
.Panel
.__init
__(self
, parent
, id, pos
, size
, style
, name
)
62 self
.running
= (1 != 1)
63 _seqTypes
= (type([]), type(()))
65 # set size, guessing if necessary
68 if type(bitmap
) in _seqTypes
:
69 width
= bitmap
[0].GetWidth()
74 if type(bitmap
) in _seqTypes
:
75 height
= bitmap
[0].GetHeight()
77 height
= bitmap
.GetHeight()
78 self
.width
, self
.height
= width
, height
81 assert width
!= -1 and height
!= -1, "Unable to guess size"
84 extentX
, extentY
= self
.GetTextExtent(label
)
85 self
.labelX
= (width
- extentX
)/2
86 self
.labelY
= (height
- extentY
)/2
87 self
.frameDelay
= frameDelay
90 self
.autoReverse
= reverse
91 self
.overlay
= overlay
92 if overlay
is not None:
93 self
.overlay
= overlay
94 self
.overlayX
= (width
- self
.overlay
.GetWidth()) / 2
95 self
.overlayY
= (height
- self
.overlay
.GetHeight()) / 2
96 self
.showOverlay
= overlay
is not None
97 self
.showLabel
= label
is not None
99 # do we have a sequence of images?
100 if type(bitmap
) in _seqTypes
:
101 self
.submaps
= bitmap
102 self
.frames
= len(self
.submaps
)
103 # or a composite image that needs to be split?
107 for chunk
in range(frames
):
108 rect
= (chunk
* frameWidth
, 0, width
, height
)
109 self
.submaps
.append(bitmap
.GetSubBitmap(rect
))
111 # self.sequence can be changed, but it's not recommended doing it
112 # while the throbber is running. self.sequence[0] should always
113 # refer to whatever frame is to be shown when 'resting' and be sure
114 # that no item in self.sequence >= self.frames or < 0!!!
115 self
.sequence
= range(self
.frames
)
117 self
.SetClientSize((width
, height
))
120 self
.timer
= wx
.Timer(self
, timerID
)
122 EVT_UPDATE_THROBBER(self
, self
.Rotate
)
123 wx
.EVT_PAINT(self
, self
.OnPaint
)
124 wx
.EVT_TIMER(self
, timerID
, self
.OnTimer
)
125 wx
.EVT_WINDOW_DESTROY(self
, self
.OnDestroyWindow
)
128 def OnTimer(self
, event
):
129 wx
.PostEvent(self
, UpdateThrobberEvent())
132 def OnDestroyWindow(self
, event
):
138 dc
.DrawBitmap(self
.submaps
[self
.sequence
[self
.current
]], (0, 0), True)
139 if self
.overlay
and self
.showOverlay
:
140 dc
.DrawBitmap(self
.overlay
, (self
.overlayX
, self
.overlayY
), True)
141 if self
.label
and self
.showLabel
:
142 dc
.DrawText(self
.label
, (self
.labelX
, self
.labelY
))
143 dc
.SetTextForeground(wx
.WHITE
)
144 dc
.DrawText(self
.label
, (self
.labelX
-1, self
.labelY
-1))
147 def OnPaint(self
, event
):
148 self
.Draw(wx
.PaintDC(self
))
152 def Rotate(self
, event
):
153 self
.current
+= self
.direction
154 if self
.current
>= len(self
.sequence
):
157 self
.current
= len(self
.sequence
) - 1
165 self
.current
= len(self
.sequence
) - 1
166 self
.Draw(wx
.ClientDC(self
))
169 # --------- public methods ---------
170 def SetFont(self
, font
):
171 """Set the font for the label"""
172 wx
.Panel
.SetFont(self
, font
)
173 self
.SetLabel(self
.label
)
174 self
.Draw(wx
.ClientDC(self
))
178 """Stop the animation and return to frame 0"""
181 self
.Draw(wx
.ClientDC(self
))
185 """Change the direction of the animation"""
186 self
.direction
= -self
.direction
190 """Returns True if the animation is running"""
195 """Start the animation"""
197 self
.running
= not self
.running
198 self
.timer
.Start(int(self
.frameDelay
* 1000))
202 """Stop the animation"""
205 self
.running
= not self
.running
208 def SetFrameDelay(self
, frameDelay
= 0.05):
209 """Delay between each frame"""
210 self
.frameDelay
= frameDelay
216 def ToggleOverlay(self
, state
= None):
217 """Toggle the overlay image"""
219 self
.showOverlay
= not self
.showOverlay
221 self
.showOverlay
= state
222 self
.Draw(wx
.ClientDC(self
))
225 def ToggleLabel(self
, state
= None):
226 """Toggle the label"""
228 self
.showLabel
= not self
.showLabel
230 self
.showLabel
= state
231 self
.Draw(wx
.ClientDC(self
))
234 def SetLabel(self
, label
):
235 """Change the text of the label"""
238 extentX
, extentY
= self
.GetTextExtent(label
)
239 self
.labelX
= (self
.width
- extentX
)/2
240 self
.labelY
= (self
.height
- extentY
)/2
241 self
.Draw(wx
.ClientDC(self
))
245 # ------------------------------------------------------------------------------