2 from wxPython
.wx
import *
5 ## Stuff to integrate FloatCanvas into wxPython Demo
15 The FloatCanvas requires the Numeric module:
17 http://sourceforge.net/projects/numpy
19 def runTest(frame
, nb
, log
):
20 dlg
= wxMessageDialog(frame
, errorText
,
21 'Sorry', wxOK | wxICON_INFORMATION
)
28 from wxPython
.lib
import floatcanvas
29 import wxPython
.lib
.colourdb
31 ID_ABOUT_MENU
= wxNewId()
32 ID_EXIT_MENU
= wxNewId()
33 ID_ZOOM_TO_FIT_MENU
= wxNewId()
34 ID_DRAWTEST_MENU
= wxNewId()
35 ID_LINETEST_MENU
= wxNewId()
36 ID_DRAWMAP_MENU
= wxNewId()
37 ID_DRAWMAP2_MENU
= wxNewId()
38 ID_CLEAR_MENU
= wxNewId()
41 LineStyles
= floatcanvas
.draw_object
.LineStyleList
.keys()
45 class DrawFrame(wxFrame
):
49 A frame used for the FloatCanvas Demo
53 def __init__(self
,parent
, id,title
,position
,size
):
54 wxFrame
.__init
__(self
,parent
, id,title
,position
, size
)
61 file_menu
.Append(ID_EXIT_MENU
, "&Close","Close this frame")
62 EVT_MENU(self
, ID_EXIT_MENU
, self
.OnQuit
)
63 MenuBar
.Append(file_menu
, "&File")
66 draw_menu
.Append(ID_DRAWTEST_MENU
, "&Draw Test","Run a test of drawing random components")
67 EVT_MENU(self
, ID_DRAWTEST_MENU
,self
.DrawTest
)
68 draw_menu
.Append(ID_LINETEST_MENU
, "&Line Test","Run a test of drawing random lines")
69 EVT_MENU(self
, ID_LINETEST_MENU
,self
.LineTest
)
70 draw_menu
.Append(ID_DRAWMAP_MENU
, "Draw &Map","Run a test of drawing a map")
71 EVT_MENU(self
, ID_DRAWMAP_MENU
,self
.DrawMap
)
72 draw_menu
.Append(ID_CLEAR_MENU
, "&Clear","Clear the Canvas")
73 EVT_MENU(self
, ID_CLEAR_MENU
,self
.Clear
)
74 MenuBar
.Append(draw_menu
, "&Draw")
78 view_menu
.Append(ID_ZOOM_TO_FIT_MENU
, "Zoom to &Fit","Zoom to fit the window")
79 EVT_MENU(self
, ID_ZOOM_TO_FIT_MENU
,self
.ZoomToFit
)
80 MenuBar
.Append(view_menu
, "&View")
83 help_menu
.Append(ID_ABOUT_MENU
, "&About",
84 "More information About this program")
85 EVT_MENU(self
, ID_ABOUT_MENU
, self
.OnAbout
)
86 MenuBar
.Append(help_menu
, "&Help")
88 self
.SetMenuBar(MenuBar
)
90 self
.CreateStatusBar()
91 self
.SetStatusText("")
93 EVT_CLOSE(self
, self
.OnCloseWindow
)
95 # Other event handlers:
96 EVT_RIGHT_DOWN(self
, self
.RightButtonEvent
)
99 self
.Canvas
= floatcanvas
.FloatCanvas(self
,-1,(500,500),
100 ProjectionFun
= 'FlatEarth',
102 EnclosingFrame
= self
,
103 BackgroundColor
= "DARK SLATE BLUE",
108 self
.object_list
= []
112 def RightButtonEvent(self
,event
):
113 print "Right Button has been clicked in DrawFrame"
114 print "coords are: %i, %i"%(event
.GetX(),event
.GetY())
117 def OnAbout(self
, event
):
118 dlg
= wxMessageDialog(self
, "This is a small program to demonstrate\n"
119 "the use of the FloatCanvas\n",
120 "About Me", wxOK | wxICON_INFORMATION
)
124 def SetMode(self
,event
):
125 for id in [ID_ZOOM_IN_BUTTON
,ID_ZOOM_OUT_BUTTON
,ID_MOVE_MODE_BUTTON
]:
126 self
.ToolBar
.ToggleTool(id,0)
127 self
.ToolBar
.ToggleTool(event
.GetId(),1)
128 if event
.GetId() == ID_ZOOM_IN_BUTTON
:
129 self
.Canvas
.SetGUIMode("ZoomIn")
130 elif event
.GetId() == ID_ZOOM_OUT_BUTTON
:
131 self
.Canvas
.SetGUIMode("ZoomOut")
132 elif event
.GetId() == ID_MOVE_MODE_BUTTON
:
133 self
.Canvas
.SetGUIMode("Move")
135 def ZoomToFit(self
,event
):
136 self
.Canvas
.ZoomToBB()
138 def Clear(self
,event
= None):
139 self
.Canvas
.RemoveObjects(self
.object_list
)
140 self
.object_list
= []
143 def OnQuit(self
,event
):
146 def OnCloseWindow(self
, event
):
149 def DrawTest(self
,event
):
156 object_list
= self
.object_list
158 ## Random tests of everything:
162 x
,y
= (random
.uniform(Range
[0],Range
[1]),random
.uniform(Range
[0],Range
[1]))
163 lw
= random
.randint(1,5)
164 cf
= random
.randint(0,len(colors
)-1)
165 h
= random
.randint(1,5)
166 w
= random
.randint(1,5)
167 object_list
.append(Canvas
.AddRectangle(x
,y
,h
,w
,LineWidth
= lw
,FillColor
= colors
[cf
]))
171 x
,y
= (random
.uniform(Range
[0],Range
[1]),random
.uniform(Range
[0],Range
[1]))
172 lw
= random
.randint(1,5)
173 cf
= random
.randint(0,len(colors
)-1)
174 h
= random
.randint(1,5)
175 w
= random
.randint(1,5)
176 object_list
.append(Canvas
.AddEllipse(x
,y
,h
,w
,LineWidth
= lw
,FillColor
= colors
[cf
]))
180 x
,y
= (random
.uniform(Range
[0],Range
[1]),random
.uniform(Range
[0],Range
[1]))
181 D
= random
.randint(1,50)
182 lw
= random
.randint(1,5)
183 cf
= random
.randint(0,len(colors
)-1)
184 cl
= random
.randint(0,len(colors
)-1)
185 object_list
.append(Canvas
.AddDot(x
,y
,D
,LineWidth
= lw
,LineColor
= colors
[cl
],FillColor
= colors
[cf
]))
189 x
,y
= (random
.uniform(Range
[0],Range
[1]),random
.uniform(Range
[0],Range
[1]))
190 D
= random
.randint(1,5)
191 lw
= random
.randint(1,5)
192 cf
= random
.randint(0,len(colors
)-1)
193 cl
= random
.randint(0,len(colors
)-1)
194 object_list
.append(Canvas
.AddCircle(x
,y
,D
,LineWidth
= lw
,LineColor
= colors
[cl
],FillColor
= colors
[cf
]))
195 self
.object_list
.append(self
.Canvas
.AddText("Circle # %i"%(i),x
,y
,Size
= 12,BackGround
= None,Position
= "cc"))
200 for j
in range(random
.randint(2,10)):
201 point
= (random
.randint(Range
[0],Range
[1]),random
.randint(Range
[0],Range
[1]))
203 lw
= random
.randint(1,10)
204 cf
= random
.randint(0,len(colors
)-1)
205 cl
= random
.randint(0,len(colors
)-1)
206 self
.object_list
.append(self
.Canvas
.AddLine(points
, LineWidth
= lw
, LineColor
= colors
[cl
]))
211 for j
in range(random
.randint(2,6)):
212 point
= (random
.uniform(Range
[0],Range
[1]),random
.uniform(Range
[0],Range
[1]))
214 lw
= random
.randint(1,6)
215 cf
= random
.randint(0,len(colors
)-1)
216 cl
= random
.randint(0,len(colors
)-1)
217 self
.object_list
.append(self
.Canvas
.AddPolygon(points
,
219 LineColor
= colors
[cl
],
220 FillColor
= colors
[cf
],
221 FillStyle
= 'Solid'))
227 points
= RandomArray
.uniform(Range
[0],Range
[1],(100,2))
228 cf
= random
.randint(0,len(colors
)-1)
229 D
= random
.randint(1,4)
230 self
.object_list
.append(self
.Canvas
.AddPointSet(points
, Color
= colors
[cf
], Diameter
= D
))
235 ts
= random
.randint(10,40)
236 cf
= random
.randint(0,len(colors
)-1)
237 x
,y
= (random
.uniform(Range
[0],Range
[1]),random
.uniform(Range
[0],Range
[1]))
238 self
.object_list
.append(self
.Canvas
.AddText(String
,x
,y
,Size
= ts
,ForeGround
= colors
[cf
],Position
= "cc"))
240 self
.Canvas
.ZoomToBB()
242 def DrawMap(self
,event
= None):
245 ## Test of Actual Map Data
248 Shorelines
= Read_MapGen(os
.path
.join("data",'world.dat'),stats
= 0)
249 print "It took %f seconds to load %i shorelines"%(time
.clock() - start
,len(Shorelines
) )
251 for segment
in Shorelines
:
252 self
.object_list
.append(self
.Canvas
.AddLine(segment
))
253 print "It took %f seconds to add %i shorelines"%(time
.clock() - start
,len(Shorelines
) )
255 self
.Canvas
.ZoomToBB()
256 print "It took %f seconds to draw %i shorelines"%(time
.clock() - start
,len(Shorelines
) )
258 ## def LineTest(self,event = None):
259 ## wxGetApp().Yield()
263 ## ## Test of drawing lots of lines
265 ## start = time.clock()
270 ## for i in range(500):
271 ## points = (random.randint(Range[0],Range[1]),
272 ## random.randint(Range[0],Range[1]))
273 ## linepoints.append(points)
274 ## points = (random.randint(Range[0],Range[1]),
275 ## random.randint(Range[0],Range[1]))
276 ## linepoints.append(points)
277 ## linewidths.append(random.randint(1,10) )
278 ## linecolors.append(colors[random.randint(0,len(colors)-1) ])
279 ## linestyles.append(LineStyles[random.randint(0, len(LineStyles)-1)])
281 ## self.object_list.append(self.Canvas.AddLineSet(linepoints, LineWidths = linewidths, LineColors = linecolors, LineStyles = linestyles))
282 ## print "It took %f seconds to add %i lines"%(time.clock() - start,len(linepoints) )
283 ## start = time.clock()
284 ## self.Canvas.ZoomToBB()
285 ## print "It took %f seconds to draw %i lines"%(time.clock() - start,len(linepoints) )
287 def LineTest(self
,event
= None):
292 ## Test of drawing lots of lines
298 for i
in range(2000):
299 points
= (random
.randint(Range
[0],Range
[1]),
300 random
.randint(Range
[0],Range
[1]),
301 random
.randint(Range
[0],Range
[1]),
302 random
.randint(Range
[0],Range
[1]))
303 linepoints
.append(points
)
304 linewidths
.append(random
.randint(1,10) )
305 linecolors
.append(random
.randint(0,len(colors
)-1) )
306 for (points
,color
,width
) in zip(linepoints
,linecolors
,linewidths
):
307 self
.object_list
.append(self
.Canvas
.AddLine((points
[0:2],points
[2:4]), LineWidth
= width
, LineColor
= colors
[color
]))
308 print "It took %f seconds to add %i lines"%(time
.clock() - start
,len(linepoints
) )
310 self
.Canvas
.ZoomToBB()
311 print "It took %f seconds to draw %i lines"%(time
.clock() - start
,len(linepoints
) )
313 class DemoApp(wxApp
):
317 Under the Draw menu, there are three options:
319 *Draw Test: will put up a picture of a bunch of randomly generated
320 objects, of each kind supported.
322 *Draw Map: will draw a map of the world. Be patient, it is a big map,
323 with a lot of data, and will take a while to load and draw (about 10 sec
324 on my 450Mhz PIII). Redraws take about 2 sec. This demonstrates how the
325 performance is not very good for large drawings.
327 *Clear: Clears the Canvas.
329 Once you have a picture drawn, you can zoom in and out and move about
330 the picture. There is a tool bar with three tools that can be
333 The magnifying glass with the plus is the zoom in tool. Once selected,
334 if you click the image, it will zoom in, centered on where you
335 clicked. If you click and drag the mouse, you will get a rubber band
336 box, and the image will zoom to fit that box when you release it.
338 The magnifying glass with the minus is the zoom out tool. Once selected,
339 if you click the image, it will zoom out, centered on where you
340 clicked. (note that this takes a while when you are looking at the map,
341 as it has a LOT of lines to be drawn. The image is double buffered, so
342 you don't see the drawing in progress)
344 The hand is the move tool. Once selected, if you click and drag on the
345 image, it will move so that the part you clicked on ends up where you
346 release the mouse. Nothing is changed while you are dragging. The
347 drawing is too slow for that.
349 I'd like the cursor to change as you change tools, but the stock
350 wxCursors didn't include anything I liked, so I stuck with the
351 pointer. Please let me know if you have any nice cursor images for me to
355 Any bugs, comments, feedback, questions, and especially code are welcome:
359 Chris.Barker@noaa.gov
365 wxPython
.lib
.colourdb
.updateColourDB()
366 colors
= wxPython
.lib
.colourdb
.getColourList()
368 frame
= DrawFrame(None, -1, "FloatCanvas Demo App",wxDefaultPosition
,wxSize(700,700))
370 self
.SetTopWindow(frame
)
374 def Read_MapGen(filename
,stats
= 0,AllLines
=0):
376 This function reads a MapGen Format file, and
377 returns a list of NumPy arrays with the line segments in them.
379 Each NumPy array in the list is an NX2 array of Python Floats.
381 The demo should have come with a file, "world.dat" that is the
382 shorelines of the whole world, in MapGen format.
386 from Numeric
import array
387 file = open(filename
,'rt')
388 data
= file.readlines()
389 data
= map(string
.strip
,data
)
395 if line
== "# -b": #New segment beginning
396 if segment
: Shorelines
.append(array(segment
))
399 segment
.append(map(float,string
.split(line
)))
400 if segment
: Shorelines
.append(array(segment
))
403 NumSegments
= len(Shorelines
)
405 for segment
in Shorelines
:
406 NumPoints
= NumPoints
+ len(segment
)
407 AvgPoints
= NumPoints
/ NumSegments
408 print "Number of Segments: ", NumSegments
409 print "Average Number of Points per segment: ",AvgPoints
412 for segment
in Shorelines
:
413 Lines
.append(segment
[0])
414 for point
in segment
[1:-1]:
417 Lines
.append(segment
[-1])
419 #for point in Lines: print point
425 #----------------------------------------------------------------------
427 def runTest(frame
, nb
, log
):
429 This method is used by the wxPython Demo Framework for integrating
430 this demo with the rest.
433 wxPython
.lib
.colourdb
.updateColourDB()
434 colors
= wxPython
.lib
.colourdb
.getColourList()
436 win
= DrawFrame(None, -1, "FloatCanvas Drawing Window",wxDefaultPosition
,wxSize(500,500))
443 ## for the wxPython demo:
444 overview
= floatcanvas
.FloatCanvas
.__doc
__
448 if __name__
== "__main__":