]>
Commit | Line | Data |
---|---|---|
d14a1e28 RD |
1 | #---------------------------------------------------------------------- |
2 | # Name: wxPython.lib.analogclock | |
3 | # Purpose: A simple analog clock window | |
4 | # | |
5 | # Author: several folks on wxPython-users | |
6 | # | |
7 | # Created: 16-April-2003 | |
8 | # RCS-ID: $Id$ | |
9 | # Copyright: (c) 2003 by Total Control Software | |
10 | # Licence: wxWindows license | |
11 | #---------------------------------------------------------------------- | |
12 | ||
13 | import math, sys, string, time | |
14 | from wxPython.wx import * | |
15 | ||
16 | ||
17 | ||
18 | class AnalogClockWindow(wxWindow): | |
19 | """A simple analog clock window""" | |
20 | ||
21 | TICKS_NONE = 0 | |
22 | TICKS_SQUARE = 1 | |
23 | TICKS_CIRCLE = 2 | |
24 | ||
25 | def __init__(self, parent, ID=-1, pos=wxDefaultPosition, size=wxDefaultSize, | |
26 | style=0, name="clock"): | |
27 | # Initialize the wxWindow... | |
28 | wxWindow.__init__(self, parent, ID, pos, size, style, name) | |
29 | ||
30 | # Initialize the default clock settings... | |
31 | self.minuteMarks = 60 | |
32 | self.hourMarks = 12 | |
33 | self.tickMarksBrushC = self.GetForegroundColour() | |
34 | self.tickMarksPenC = self.GetForegroundColour() | |
35 | self.tickMarkStyle = self.TICKS_SQUARE | |
36 | ||
37 | # Make an initial bitmap for the face, it will be updated and | |
38 | # painted at the first EVT_SIZE event. | |
39 | W, H = size | |
40 | self.faceBitmap = wxEmptyBitmap(max(W,1), max(H,1)) | |
41 | ||
42 | # Initialize the timer that drives the update of the clock | |
43 | # face. Update every half second to ensure that there is at | |
44 | # least one true update during each realtime second. | |
45 | self.timer = wxTimer(self) | |
46 | self.timer.Start(500) | |
47 | ||
48 | # Set event handlers... | |
49 | EVT_PAINT(self, self.OnPaint) | |
50 | EVT_ERASE_BACKGROUND(self, lambda x: None) | |
51 | EVT_SIZE(self, self.OnSize) | |
52 | EVT_TIMER(self, -1, self.OnTimerExpire) | |
53 | EVT_WINDOW_DESTROY(self, self.OnQuit) | |
54 | ||
55 | ||
56 | def SetTickMarkStyle(self, style): | |
57 | """ | |
58 | Set the style of the marks around the edge of the clock. | |
59 | Options are TICKS_NONE, TICKS_SQUARE, and TICKS_CIRCLE | |
60 | """ | |
61 | self.tickMarkStyle = style | |
62 | ||
63 | ||
64 | def SetTickMarkColours(self, brushC, penC="BLACK"): | |
65 | """ | |
66 | Set the brush colour and optionally the pen colour of | |
67 | the marks around the edge of the clock. | |
68 | """ | |
69 | self.tickMarksBrushC = brushC | |
70 | self.tickMarksPenC = penC | |
71 | ||
72 | SetTickMarkColour = SetTickMarkColours | |
73 | ||
74 | ||
75 | def SetHandsColour(self, c): | |
76 | """An alias for SetForegroundColour""" | |
77 | self.SetForegroundColour(c) # the hands just use the foreground colour | |
78 | ||
79 | ||
80 | ||
81 | # Using the current settings, render the points and line endings for the | |
82 | # circle inside the specified device context. In this case, the DC is | |
83 | # a memory based device context that will be blitted to the actual | |
84 | # display DC inside the OnPaint() event handler. | |
85 | def OnSize(self, event): | |
86 | # The faceBitmap init is done here, to make sure the buffer is always | |
87 | # the same size as the Window | |
88 | size = self.GetClientSize() | |
89 | self.faceBitmap = wxEmptyBitmap(size.width, size.height) | |
90 | self.DrawFace() | |
91 | ||
92 | ||
93 | def OnPaint(self, event): | |
94 | self.DrawHands(wxPaintDC(self)) | |
95 | ||
96 | ||
97 | def OnQuit(self, event): | |
98 | self.timer.Stop() | |
99 | del self.timer | |
100 | ||
101 | ||
102 | def OnTimerExpire(self, event): | |
103 | self.DrawHands(wxClientDC(self)) | |
104 | ||
105 | ||
106 | def DrawHands(self, drawDC): | |
107 | # Start by drawing the face bitmap | |
108 | drawDC.DrawBitmap(self.faceBitmap, (0,0)) | |
109 | ||
110 | currentTime = time.localtime(time.time()) | |
111 | hour, minutes, seconds = currentTime[3:6] | |
112 | ||
113 | W,H = self.faceBitmap.GetWidth(), self.faceBitmap.GetHeight() | |
114 | centerX = W / 2 | |
115 | centerY = H / 2 | |
116 | ||
117 | radius = min(centerX, centerY) | |
118 | hour += minutes / 60.0 # added so the hour hand moves continuously | |
119 | x, y = self.point(hour, 12, (radius * .65)) | |
120 | hourX, hourY = (x + centerX), (centerY - y) | |
121 | x, y = self.point(minutes, 60, (radius * .85)) | |
122 | minutesX, minutesY = (x + centerX), (centerY - y) | |
123 | x, y = self.point(seconds, 60, (radius * .85)) | |
124 | secondsX, secondsY = (x + centerX), (centerY - y) | |
125 | ||
126 | # Draw the hour hand... | |
127 | drawDC.SetPen(wxPen(self.GetForegroundColour(), 5, wxSOLID)) | |
128 | drawDC.DrawLine((centerX, centerY), (hourX, hourY)) | |
129 | ||
130 | # Draw the minutes hand... | |
131 | drawDC.SetPen(wxPen(self.GetForegroundColour(), 3, wxSOLID)) | |
132 | drawDC.DrawLine((centerX, centerY), (minutesX, minutesY)) | |
133 | ||
134 | # Draw the seconds hand... | |
135 | drawDC.SetPen(wxPen(self.GetForegroundColour(), 1, wxSOLID)) | |
136 | drawDC.DrawLine((centerX, centerY), (secondsX, secondsY)) | |
137 | ||
138 | ||
139 | # Draw the specified set of line marks inside the clock face for the | |
140 | # hours or minutes... | |
141 | def DrawFace(self): | |
142 | backgroundBrush = wxBrush(self.GetBackgroundColour(), wxSOLID) | |
143 | drawDC = wxMemoryDC() | |
144 | drawDC.SelectObject(self.faceBitmap) | |
145 | drawDC.SetBackground(backgroundBrush) | |
146 | drawDC.Clear() | |
147 | ||
148 | W,H = self.faceBitmap.GetWidth(), self.faceBitmap.GetHeight() | |
149 | centerX = W / 2 | |
150 | centerY = H / 2 | |
151 | ||
152 | # Draw the marks for hours and minutes... | |
153 | self.DrawTimeMarks(drawDC, self.minuteMarks, centerX, centerY, 4) | |
154 | self.DrawTimeMarks(drawDC, self.hourMarks, centerX, centerY, 9) | |
155 | ||
156 | ||
157 | def DrawTimeMarks(self, drawDC, markCount, centerX, centerY, markSize): | |
158 | for i in range(markCount): | |
159 | x, y = self.point(i + 1, markCount, min(centerX,centerY) - 16) | |
160 | scaledX = x + centerX - markSize/2 | |
161 | scaledY = centerY - y - markSize/2 | |
162 | ||
163 | drawDC.SetBrush(wxBrush(self.tickMarksBrushC, wxSOLID)) | |
164 | drawDC.SetPen(wxPen(self.tickMarksPenC, 1, wxSOLID)) | |
165 | if self.tickMarkStyle != self.TICKS_NONE: | |
166 | if self.tickMarkStyle == self.TICKS_CIRCLE: | |
167 | drawDC.DrawEllipse((scaledX - 2, scaledY), (markSize, markSize)) | |
168 | else: | |
169 | drawDC.DrawRectangle((scaledX - 3, scaledY), (markSize, markSize)) | |
170 | ||
171 | ||
172 | def point(self, tick, range, radius): | |
173 | angle = tick * (360.0 / range) | |
174 | radiansPerDegree = math.pi / 180 | |
175 | pointX = int(round(radius * math.sin(angle * radiansPerDegree))) | |
176 | pointY = int(round(radius * math.cos(angle * radiansPerDegree))) | |
177 | return wxPoint(pointX, pointY) | |
178 | ||
179 | ||
180 | ||
181 | ||
182 | if __name__ == "__main__": | |
183 | class App(wxApp): | |
184 | def OnInit(self): | |
185 | frame = wxFrame(None, -1, "AnalogClockWindow Test", size=(375,375)) | |
186 | ||
187 | clock = AnalogClockWindow(frame) | |
188 | clock.SetTickMarkColours("RED") | |
189 | clock.SetHandsColour("WHITE") | |
190 | clock.SetBackgroundColour("BLUE") | |
191 | ||
192 | frame.Centre(wxBOTH) | |
193 | frame.Show(True) | |
194 | self.SetTopWindow(frame) | |
195 | return true | |
196 | ||
197 | theApp = App(0) | |
198 | theApp.MainLoop() | |
199 | ||
1fded56b | 200 | |
1fded56b | 201 |