Add the FloatCanvas demo modules

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@73860 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2013-04-26 07:04:14 +00:00
parent e31baa0d8e
commit c7cd5d5fe9
41 changed files with 6278 additions and 0 deletions

304
samples/floatcanvas/Animation.py Executable file
View File

@@ -0,0 +1,304 @@
#!/usr/bin/env python
"""
A test of some simple animation
this is very old-style code: don't imitate it!
"""
from time import clock
import wx
from numpy import *
## import local version:
import sys
#ver = 'local'
ver = 'installed'
if ver == 'installed': ## import the installed version
from wx.lib.floatcanvas import NavCanvas
from wx.lib.floatcanvas import FloatCanvas
print "using installed version:", wx.lib.floatcanvas.__version__
elif ver == 'local':
## import a local version
import sys
sys.path.append("..")
from floatcanvas import NavCanvas
from floatcanvas import FloatCanvas
ID_DRAW_BUTTON = 100
ID_QUIT_BUTTON = 101
ID_CLEAR_BUTTON = 103
ID_ZOOM_IN_BUTTON = 104
ID_ZOOM_OUT_BUTTON = 105
ID_ZOOM_TO_FIT_BUTTON = 110
ID_MOVE_MODE_BUTTON = 111
ID_TEST_BUTTON = 112
ID_ABOUT_MENU = 200
ID_EXIT_MENU = 201
ID_ZOOM_IN_MENU = 202
ID_ZOOM_OUT_MENU = 203
ID_ZOOM_TO_FIT_MENU = 204
ID_DRAWTEST_MENU = 205
ID_DRAWMAP_MENU = 206
ID_CLEAR_MENU = 207
ID_TEST = 500
class DrawFrame(wx.Frame):
def __init__(self,parent, id,title,position,size):
wx.Frame.__init__(self,parent, id,title,position, size)
## Set up the MenuBar
MenuBar = wx.MenuBar()
file_menu = wx.Menu()
file_menu.Append(ID_EXIT_MENU, "E&xit","Terminate the program")
wx.EVT_MENU(self, ID_EXIT_MENU, self.OnQuit)
MenuBar.Append(file_menu, "&File")
draw_menu = wx.Menu()
draw_menu.Append(ID_DRAWTEST_MENU, "&Draw Test","Run a test of drawing random components")
wx.EVT_MENU(self, ID_DRAWTEST_MENU,self.DrawTest)
draw_menu.Append(ID_DRAWMAP_MENU, "Draw &Movie","Run a test of drawing a map")
wx.EVT_MENU(self, ID_DRAWMAP_MENU,self.RunMovie)
draw_menu.Append(ID_CLEAR_MENU, "&Clear","Clear the Canvas")
wx.EVT_MENU(self, ID_CLEAR_MENU,self.Clear)
MenuBar.Append(draw_menu, "&Draw")
view_menu = wx.Menu()
view_menu.Append(ID_ZOOM_TO_FIT_MENU, "Zoom to &Fit","Zoom to fit the window")
wx.EVT_MENU(self, ID_ZOOM_TO_FIT_MENU,self.ZoomToFit)
MenuBar.Append(view_menu, "&View")
help_menu = wx.Menu()
help_menu.Append(ID_ABOUT_MENU, "&About",
"More information About this program")
wx.EVT_MENU(self, ID_ABOUT_MENU, self.OnAbout)
MenuBar.Append(help_menu, "&Help")
self.SetMenuBar(MenuBar)
self.CreateStatusBar()
self.SetStatusText("")
wx.EVT_CLOSE(self, self.OnCloseWindow)
# Other event handlers:
wx.EVT_RIGHT_DOWN(self, self.RightButtonEvent)
# Add the Canvas
self.Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
Debug = False,
BackgroundColor = "WHITE").Canvas
self.Canvas.NumBetweenBlits = 1000
self.Show(True)
self.DrawTest(None)
return None
def RightButtonEvent(self,event):
print "Right Button has been clicked in DrawFrame"
print "coords are: %i, %i"%(event.GetX(),event.GetY())
event.Skip()
def OnAbout(self, event):
dlg = wx.MessageDialog(self, "This is a small program to demonstrate\n"
"the use of the FloatCanvas\n",
"About Me", wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def ZoomToFit(self,event):
self.Canvas.ZoomToBB()
def Clear(self,event = None):
self.Canvas.ClearAll()
self.Canvas.Draw()
def OnQuit(self,event):
self.Close(True)
def OnCloseWindow(self, event):
self.Destroy()
def DrawTest(self,event = None):
import random
import numpy.random as RandomArray
Range = (-10,10)
colors = ["AQUAMARINE", "BLACK", "BLUE", "BLUE VIOLET", "BROWN",
"CADET BLUE", "CORAL", "CORNFLOWER BLUE", "CYAN", "DARK GREY",
"DARK GREEN", "DARK OLIVE GREEN", "DARK ORCHID", "DARK SLATE BLUE",
"DARK SLATE GREY", "DARK TURQUOISE", "DIM GREY",
"FIREBRICK", "FOREST GREEN", "GOLD", "GOLDENROD", "GREY",
"GREEN", "GREEN YELLOW", "INDIAN RED", "KHAKI", "LIGHT BLUE",
"LIGHT GREY", "LIGHT STEEL BLUE", "LIME GREEN", "MAGENTA",
"MAROON", "MEDIUM AQUAMARINE", "MEDIUM BLUE", "MEDIUM FOREST GREEN",
"MEDIUM GOLDENROD", "MEDIUM ORCHID", "MEDIUM SEA GREEN",
"MEDIUM SLATE BLUE", "MEDIUM SPRING GREEN", "MEDIUM TURQUOISE",
"MEDIUM VIOLET RED", "MIDNIGHT BLUE", "NAVY", "ORANGE", "ORANGE RED",
"ORCHID", "PALE GREEN", "PINK", "PLUM", "PURPLE", "RED",
"SALMON", "SEA GREEN", "SIENNA", "SKY BLUE", "SLATE BLUE",
"SPRING GREEN", "STEEL BLUE", "TAN", "THISTLE", "TURQUOISE",
"VIOLET", "VIOLET RED", "WHEAT", "WHITE", "YELLOW", "YELLOW GREEN"]
Canvas = self.Canvas
# Some Polygons in the background:
# for i in range(500):
# points = RandomArray.uniform(-100,100,(10,2))
for i in range(500):
# for i in range(1):
points = RandomArray.uniform(-100,100,(10,2))
lw = random.randint(1,6)
cf = random.randint(0,len(colors)-1)
cl = random.randint(0,len(colors)-1)
self.Canvas.AddPolygon(points,
LineWidth = lw,
LineColor = colors[cl],
FillColor = colors[cf],
FillStyle = 'Solid',
InForeground = False)
## Pointset
print "Adding Points to Foreground"
for i in range(1):
points = RandomArray.uniform(-100,100,(1000,2))
D = 2
self.LEs = self.Canvas.AddPointSet(points, Color = "Black", Diameter = D, InForeground = True)
self.Canvas.AddRectangle((-200,-200), (400,400))
Canvas.ZoomToBB()
def RunMovie(self,event = None):
import numpy.random as RandomArray
start = clock()
#shift = RandomArray.randint(0,0,(2,))
for i in range(100):
points = self.LEs.Points
shift = RandomArray.randint(-5,6,(2,))
points += shift
self.LEs.SetPoints(points)
self.Canvas.Draw()
wx.GetApp().Yield(True)
print "running the movie took %f seconds"%(clock() - start)
class DemoApp(wx.App):
"""
How the demo works:
Under the Draw menu, there are three options:
*Draw Test: will put up a picture of a bunch of randomly generated
objects, of each kind supported.
*Draw Map: will draw a map of the world. Be patient, it is a big map,
with a lot of data, and will take a while to load and draw (about 10 sec
on my 450Mhz PIII). Redraws take about 2 sec. This demonstrates how the
performance is not very good for large drawings.
*Clear: Clears the Canvas.
Once you have a picture drawn, you can zoom in and out and move about
the picture. There is a tool bar with three tools that can be
selected.
The magnifying glass with the plus is the zoom in tool. Once selected,
if you click the image, it will zoom in, centered on where you
clicked. If you click and drag the mouse, you will get a rubber band
box, and the image will zoom to fit that box when you release it.
The magnifying glass with the minus is the zoom out tool. Once selected,
if you click the image, it will zoom out, centered on where you
clicked. (note that this takes a while when you are looking at the map,
as it has a LOT of lines to be drawn. The image is double buffered, so
you don't see the drawing in progress)
The hand is the move tool. Once selected, if you click and drag on the
image, it will move so that the part you clicked on ends up where you
release the mouse. Nothing is changed while you are dragging. The
drawing is too slow for that.
I'd like the cursor to change as you change tools, but the stock
wx.Cursors didn't include anything I liked, so I stuck with the
pointer. Pleae let me know if you have any nice cursor images for me to
use.
Any bugs, comments, feedback, questions, and especially code are welcome:
-Chris Barker
ChrisHBarker@home.net
http://members.home.net/barkerlohmann
"""
def OnInit(self):
wx.InitAllImageHandlers()
frame = DrawFrame(None, -1, "Simple Drawing Window",wx.DefaultPosition, (700,700) )
self.SetTopWindow(frame)
return True
def Read_MapGen(filename,stats = False):
"""
This function reads a MapGen Format file, and
returns a list of NumPy arrays with the line segments in them.
Each NumPy array in the list is an NX2 array of Python Floats.
The demo should have come with a file, "world.dat" that is the
shorelines of the whole worls, in MapGen format.
"""
import string
from numpy import array
file = open(filename,'rt')
data = file.readlines()
data = map(string.strip,data)
Shorelines = []
segment = []
for line in data:
if line == "# -b": #New segment begining
if segment: Shorelines.append(array(segment))
segment = []
else:
segment.append(map(float,string.split(line)))
if segment: Shorelines.append(array(segment))
if stats:
NumSegments = len(Shorelines)
NumPoints = False
for segment in Shorelines:
NumPoints = NumPoints + len(segment)
AvgPoints = NumPoints / NumSegments
print "Number of Segments: ", NumSegments
print "Average Number of Points per segment: ",AvgPoints
return Shorelines
if __name__ == "__main__":
app = DemoApp(0)
app.MainLoop()

133
samples/floatcanvas/BB_HitTest.py Executable file
View File

@@ -0,0 +1,133 @@
#!/usr/bin/env python
"""
Test of an alternaive hit test methoid that used the bounding boxes of teh objects instead.
Poorly tested!
Edited from code contributed by Benjamin Jessup on the mailing list
"""
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
FC = FloatCanvas
def BB_HitTest(self, event, HitEvent):
""" Hit Test Function for BoundingBox Based HitMap System"""
if self.HitDict and self.HitDict[HitEvent]:
# loop though the objects associated with this event
objects = [] #Create object list for holding multiple objects
object_index_list = [] #Create list for holding the indexes
xy_p = event.GetPosition()
xy = self.PixelToWorld( xy_p ) #Convert to the correct coords
for key2 in self.HitDict[HitEvent].keys():
#Get Mouse Event Position
bb = self.HitDict[HitEvent][key2].BoundingBox
if bb.PointInside(xy):
Object = self.HitDict[HitEvent][key2]
objects.append(Object)
try:
#First try the foreground index and add the length of the background index
#to account for the two 'layers' that already exist in the code
index = self._ForeDrawList.index(Object) + len(self._DrawList)
except ValueError:
index = self._DrawList.index(Object) #Now check background if not found in foreground
object_index_list.append(index) #append the index found
else:
Object = self.HitDict[HitEvent][key2]
if len(objects) > 0: #If no objects then do nothing
#Get the highest index object
highest_object = objects[object_index_list.index(max(object_index_list))]
highest_object.HitCoords = xy
highest_object.HitCoordsPixel = xy_p
highest_object.CallBackFuncs[HitEvent](highest_object)
return True
else:
return False
return False
FC.FloatCanvas.HitTest = BB_HitTest
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
Point = (45,40)
Text = Canvas.AddScaledText("A String",
Point,
20,
Color = "Black",
BackgroundColor = None,
Family = wx.ROMAN,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'bl',
InForeground = False)
Text.MinFontSize = 4 # the default is 1
Text.DisappearWhenSmall = False #the default is True
Rect1 = Canvas.AddRectangle((50, 20), (40,15), FillColor="Red", LineStyle = None)
Rect1.Bind(FC.EVT_FC_LEFT_DOWN, self.OnLeft)
Rect1.Name = "red"
Rect2 = Canvas.AddRectangle((70, 30), (40,15), FillColor="Blue", LineStyle = None)
Rect2.Bind(FC.EVT_FC_LEFT_DOWN, self.OnLeft)
Rect2.Name = 'blue'
self.Show()
Canvas.ZoomToBB()
def OnLeft(self, object):
print "Rect %s got hit"%object.Name
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

353
samples/floatcanvas/BNAEditor.py Executable file
View File

@@ -0,0 +1,353 @@
#!/usr/bin/env python
"""
BNA-Editor: a simple app for editing polygons in BNA files
BNA is a simple text format for storing polygons in lat-long coordinates.
"""
import os, sys
import sets
import numpy as N
#### import local version:
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
import wx
import sys
if len(sys.argv) > 1:
StartFileName = sys.argv[1]
else:
StartFileName = None
### These utilities are required to load and save BNA data.
class BNAData:
"""
Class to store the full set of data in a BNA file
"""
def __init__(self, Filename = None):
self.Filename = Filename
self.PointsData = None
self.Filename = None
self.Names = None
self.Types = None
if Filename is not None:
self.Load(Filename)
def __getitem__(self,index):
return (self.PointsData[index], self.Names[index])
def __len__(self):
return len(self.PointsData)
def Save(self, filename = None):
if not filename:
filename = self.filename
file = open(filename, 'w')
for i, points in enumerate(self.PointsData):
file.write('"%s","%s", %i\n'%(self.Names[i],self.Types[i],len(points) ) )
for p in points:
file.write("%.12f,%.12f\n"%(tuple(p)))
def Load(self, filename):
#print "Loading:", filename
file = open(filename,'rU')
self.Filename = filename
self.PointsData = []
self.Names = []
self.Types = []
while 1:
line = file.readline()
if not line:
break
line = line.strip()
Name, line = line.split('","')
Name = Name[1:]
Type,line = line.split('",')
num_points = int(line)
self.Types.append(Type)
self.Names.append(Name)
polygon = N.zeros((num_points,2),N.float)
for i in range(num_points):
polygon[i,:] = map(float, file.readline().split(','))
self.PointsData.append(polygon)
file.close()
return None
class DrawFrame(wx.Frame):
"""
A frame used for the BNA Editor
"""
def __init__(self,parent, id,title,position,size):
wx.Frame.__init__(self,parent, id,title,position, size)
## Set up the MenuBar
MenuBar = wx.MenuBar()
FileMenu = wx.Menu()
OpenMenu = FileMenu.Append(wx.ID_ANY, "&Open","Open BNA")
self.Bind(wx.EVT_MENU, self.OpenBNA, OpenMenu)
SaveMenu = FileMenu.Append(wx.ID_ANY, "&Save","Save BNA")
self.Bind(wx.EVT_MENU, self.SaveBNA, SaveMenu)
CloseMenu = FileMenu.Append(wx.ID_ANY, "&Close","Close Application")
self.Bind(wx.EVT_MENU, self.OnQuit, CloseMenu)
MenuBar.Append(FileMenu, "&File")
view_menu = wx.Menu()
ZoomMenu = view_menu.Append(wx.ID_ANY, "Zoom to &Fit","Zoom to fit the window")
self.Bind(wx.EVT_MENU, self.ZoomToFit, ZoomMenu)
MenuBar.Append(view_menu, "&View")
help_menu = wx.Menu()
AboutMenu = help_menu.Append(wx.ID_ANY, "&About",
"More information About this program")
self.Bind(wx.EVT_MENU, self.OnAbout, AboutMenu)
MenuBar.Append(help_menu, "&Help")
self.SetMenuBar(MenuBar)
self.CreateStatusBar()
# Add the Canvas
self.Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
Debug = 0,
BackgroundColor = "DARK SLATE BLUE"
).Canvas
wx.EVT_CLOSE(self, self.OnCloseWindow)
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
FloatCanvas.EVT_LEFT_UP(self.Canvas, self.OnLeftUp )
FloatCanvas.EVT_LEFT_DOWN(self.Canvas, self.OnLeftDown)
try:
self.FileDialog = wx.FileDialog(self, "Pick a BNA file",".","","*", wx.OPEN)
except wx._core.PyAssertionError:
self.FileDialog = None
self.ResetSelections()
return None
def ResetSelections(self):
self.SelectedPoly = None
self.SelectedPolyOrig = None
self.SelectedPoints = None
self.PointSelected = False
self.SelectedPointNeighbors = None
def OnLeftDown(self,event):
if self.SelectedPoly:
self.DeSelectPoly()
self.Canvas.Draw()
def OnAbout(self, event):
dlg = wx.MessageDialog(self, "This is a small program to demonstrate\n"
"the use of the FloatCanvas\n",
"About Me", wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def ZoomToFit(self,event):
self.Canvas.ZoomToBB()
def OpenBNA(self, event):
if self.FileDialog is None:
self.FileDialog = wx.FileDialog(self, "Pick a BNA file",style= wx.OPEN)
dlg = self.FileDialog
dlg.SetMessage("Pick a BNA file")
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPath()
self.LoadBNA(filename)
def SaveBNA(self, event):
for i in self.ChangedPolys:
self.BNAFile.PointsData[i] = self.AllPolys[i].Points
dlg = wx.FileDialog(self,
message="Pick a BNA file",
style=wx.SAVE)
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPath()
self.BNAFile.Save(filename)
def Clear(self,event = None):
self.Canvas.ClearAll()
self.Canvas.Draw(True)
def OnQuit(self,event):
self.Close(True)
def OnCloseWindow(self, event):
self.Destroy()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
And moves a point if there is one
"""
self.SetStatusText("%.4f, %.4f"%tuple(event.Coords))
if self.PointSelected:
PolyPoints = self.SelectedPoly.Points
Index = self.SelectedPoints.Index
dc = wx.ClientDC(self.Canvas)
PixelCoords = event.GetPosition()
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetLogicalFunction(wx.XOR)
if self.SelectedPointNeighbors is None:
self.SelectedPointNeighbors = N.zeros((3,2), N.float)
#fixme: This feels very inelegant!
if Index == 0:
self.SelectedPointNeighbors[0] = self.SelectedPoly.Points[-1]
self.SelectedPointNeighbors[1:3] = self.SelectedPoly.Points[:2]
elif Index == len(self.SelectedPoly.Points)-1:
self.SelectedPointNeighbors[0:2] = self.SelectedPoly.Points[-2:]
self.SelectedPointNeighbors[2] = self.SelectedPoly.Points[0]
else:
self.SelectedPointNeighbors = self.SelectedPoly.Points[Index-1:Index+2]
self.SelectedPointNeighbors = self.Canvas.WorldToPixel(self.SelectedPointNeighbors)
else:
dc.DrawLines(self.SelectedPointNeighbors)
self.SelectedPointNeighbors[1] = PixelCoords
dc.DrawLines(self.SelectedPointNeighbors)
def OnLeftUp(self, event):
if self.PointSelected:
self.SelectedPoly.Points[self.SelectedPoints.Index] = event.GetCoords()
self.SelectedPoly.SetPoints(self.SelectedPoly.Points, copy = False)
self.SelectedPoints.SetPoints(self.SelectedPoly.Points, copy = False)
self.PointSelected = False
self.SelectedPointNeighbors = None
self.SelectedPoly.HasChanged = True
self.Canvas.Draw()
def DeSelectPoly(self):
Canvas = self.Canvas
if self.SelectedPoly.HasChanged:
self.ChangedPolys.add(self.SelectedPolyOrig.BNAIndex)
self.SelectedPolyOrig.SetPoints(self.SelectedPoly.Points, copy = False)
self.Canvas.Draw(Force = True)
Canvas.RemoveObject(self.SelectedPoly)
Canvas.RemoveObject(self.SelectedPoints)
self.ResetSelections()
def SelectPoly(self, Object):
Canvas = self.Canvas
if Object is self.SelectedPolyOrig:
pass
else:
if self.SelectedPoly is not None:
self.DeSelectPoly()
self.SelectedPolyOrig = Object
self.SelectedPoly = Canvas.AddPolygon(Object.Points,
LineWidth = 1,
LineColor = "Red",
FillColor = None,
InForeground = True)
self.SelectedPoly.HasChanged = False
# Draw points on the Vertices of the Selected Poly:
self.SelectedPoints = Canvas.AddPointSet(Object.Points,
Diameter = 4,
Color = "Red",
InForeground = True)
self.SelectedPoints.HitLineWidth = 8 # make it a bit easier to hit
self.SelectedPoints.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.SelectPointHit)
Canvas.Draw()
def SelectPointHit(self, PointSet):
PointSet.Index = PointSet.FindClosestPoint(PointSet.HitCoords)
self.PointSelected = True
def LoadBNA(self, filename):
self.ResetSelections()
self.Canvas.ClearAll()
self.Canvas.SetProjectionFun('FlatEarth')
try:
AllPolys = []
self.BNAFile = BNAData(filename)
print "loaded BNAFile:", self.BNAFile.Filename
for i, shoreline in enumerate(self.BNAFile.PointsData):
Poly = self.Canvas.AddPolygon(shoreline,
LineWidth = 1,
LineColor = "Black",
FillColor = "Brown",
FillStyle = 'Solid')
Poly.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.SelectPoly)
Poly.BNAIndex = i
AllPolys.append(Poly)
self.Canvas.ZoomToBB()
self.ChangedPolys = sets.Set()
self.AllPolys = AllPolys
except:
#raise
dlg = wx.MessageDialog(None,
'There was something wrong with the selected bna file',
'File Loading Error',
wx.OK | wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()
class BNAEditor(wx.App):
"""
Once you have a picture drawn, you can zoom in and out and move about
the picture. There is a tool bar with three tools that can be
selected.
"""
def __init__(self, *args, **kwargs):
wx.App.__init__(self, *args, **kwargs)
def OnInit(self):
frame = DrawFrame(None, -1, "BNA Editor",wx.DefaultPosition,(700,700))
self.SetTopWindow(frame)
frame.Show()
if StartFileName:
frame.LoadBNA(StartFileName)
else:
##frame.LoadBNA("Tests/Small.bna")
frame.LoadBNA("Tiny.bna")
return True
app = BNAEditor(False)# put in True if you want output to go to it's own window.
app.MainLoop()

149
samples/floatcanvas/BarPlot.py Executable file
View File

@@ -0,0 +1,149 @@
#!/usr/bin/env python
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
import numpy as N
from numpy import random as random
NumChannels = 200
MaxValue = 2000
#MaxValue = 2**24
def YScaleFun(center):
"""
Function that returns a scaling vector to scale y data to same range as x data
This is used by FloatCanvas as a "projection function", so that you can have
a different scale for X and Y. With the default projection, X and Y are the same scale.
"""
# center gets ignored in this case
return N.array((1, float(NumChannels)/MaxValue), N.float)
def ScaleWorldToPixel(self, Lengths):
"""
This is a new version of a function that will get passed to the
drawing functions of the objects, to Change a length from world to
pixel coordinates.
This version uses the "ceil" function, so that fractional pixel get
rounded up, rather than down.
Lengths should be a NX2 array of (x,y) coordinates, or
a 2-tuple, or sequence of 2-tuples.
"""
return N.ceil(( (N.asarray(Lengths, N.float)*self.TransformVector) )).astype('i')
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
FloatCanvas.FloatCanvas.ScaleWorldToPixel = ScaleWorldToPixel
NC = NavCanvas.NavCanvas(self,-1,
size = (500,500),
BackgroundColor = "DARK SLATE BLUE",
ProjectionFun = YScaleFun,
)
self.Canvas = Canvas = NC.Canvas
#self.Canvas.ScaleWorldToPixel = ScaleWorldToPixel
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
self.Values = random.randint(0, MaxValue, (NumChannels,))
self.Bars = []
self.BarWidth = 0.75
# add an X axis
Canvas.AddLine(((0,0), (NumChannels, 0 )),)
for x in N.linspace(1, NumChannels, 11):
Canvas.AddText("%i"%x, (x-1+self.BarWidth/2,0), Position="tc")
for i, Value in enumerate(self.Values):
bar = Canvas.AddRectangle(XY=(i, 0),
WH=(self.BarWidth, Value),
LineColor = None,
LineStyle = "Solid",
LineWidth = 1,
FillColor = "Red",
FillStyle = "Solid",
)
self.Bars.append(bar)
# Add a couple a button the Toolbar
tb = NC.ToolBar
tb.AddSeparator()
ResetButton = wx.Button(tb, label="Reset")
tb.AddControl(ResetButton)
ResetButton.Bind(wx.EVT_BUTTON, self.ResetData)
# PlayButton = wx.Button(tb, wx.ID_ANY, "Run")
# tb.AddControl(PlayButton)
# PlayButton.Bind(wx.EVT_BUTTON, self.RunTest)
tb.Realize()
self.Show()
Canvas.ZoomToBB()
Canvas.Draw(True)
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
channel, value = event.Coords
if 0 < channel < NumChannels :
channel = "%i,"%(channel+1)
else:
channel = ""
if value >=0:
value = "%3g"%value
else:
value = ""
self.SetStatusText("Channel: %s Value: %s"%(channel, value))
def ResetData(self, event):
self.Values = random.randint(0, MaxValue, (NumChannels,))
for i, bar in enumerate(self.Bars):
bar.SetShape(bar.XY, (self.BarWidth, self.Values[i]))
self.Canvas.Draw(Force=True)
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

View File

@@ -0,0 +1,212 @@
#!/usr/bin/env python
"""
A test of some simple animation
this is very old-style code: don't imitate it!
"""
import wx
import numpy as np
## import local version:
import sys
#ver = 'local'
ver = 'installed'
if ver == 'installed': ## import the installed version
from wx.lib.floatcanvas import NavCanvas
from wx.lib.floatcanvas import FloatCanvas
print "using installed version:", wx.lib.floatcanvas.__version__
elif ver == 'local':
## import a local version
import sys
sys.path.append("..")
from floatcanvas import NavCanvas
from floatcanvas import FloatCanvas
FC = FloatCanvas
class MovingObjectMixin: # Borrowed from MovingElements.py
"""
Methods required for a Moving object
"""
def GetOutlinePoints(self):
BB = self.BoundingBox
OutlinePoints = np.array( ( (BB[0,0], BB[0,1]),
(BB[0,0], BB[1,1]),
(BB[1,0], BB[1,1]),
(BB[1,0], BB[0,1]),
)
)
return OutlinePoints
class Ball(MovingObjectMixin, FloatCanvas.Circle):
def __init__(self, XY, Velocity, Radius=2.0, **kwargs):
self.Velocity = np.asarray(Velocity, np.float).reshape((2,))
self.Radius = Radius
self.Moving = False
FloatCanvas.Circle.__init__(self, XY, Diameter=Radius*2, FillColor="red", **kwargs)
class DrawFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
## Set up the MenuBar
MenuBar = wx.MenuBar()
file_menu = wx.Menu()
item = file_menu.Append(wx.ID_ANY, "E&xit","Terminate the program")
self.Bind(wx.EVT_MENU, self.OnQuit, item)
MenuBar.Append(file_menu, "&File")
self.SetMenuBar(MenuBar)
self.CreateStatusBar()
self.SetStatusText("")
wx.EVT_CLOSE(self, self.OnCloseWindow)
# Add the buttons
ResetButton = wx.Button(self, label="Reset")
ResetButton.Bind(wx.EVT_BUTTON, self.OnReset)
StartButton = wx.Button(self, label="Start")
StartButton.Bind(wx.EVT_BUTTON, self.OnStart)
StopButton = wx.Button(self, label="Stop")
StopButton.Bind(wx.EVT_BUTTON, self.OnStop)
butSizer = wx.BoxSizer(wx.HORIZONTAL)
butSizer.Add(StartButton, 0, wx.RIGHT, 5 )
butSizer.Add(ResetButton, 0, wx.RIGHT, 5)
butSizer.Add(StopButton, 0, )
# Add the Canvas
NC = NavCanvas.NavCanvas(self, -1, (500,500),
Debug = False,
BackgroundColor = "BLUE")
self.Canvas = NC.Canvas
self.Initialize(None)
# lay it out:
S = wx.BoxSizer(wx.VERTICAL)
S.Add(butSizer, 0, wx.ALIGN_CENTER | wx.ALL, 5)
S.Add(NC, 1, wx.EXPAND)
self.SetSizer(S)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.MoveBall, self.timer)
self.Show(True)
def OnQuit(self,event):
self.Close(True)
def OnCloseWindow(self, event):
self.Destroy()
def Initialize(self, event=None):
Canvas = self.Canvas
#Add the floor
Canvas.AddLine(( (0, 0), (100, 0) ), LineWidth=4, LineColor="Black")
# add the wall:
Canvas.AddRectangle( (0,0), (10,50), FillColor='green')
# add the ball:
self.Ball = Ball( (5, 52), (2, 0), InForeground=True )
Canvas.AddObject( self.Ball )
# to capture the mouse to move the ball
self.Ball.Bind(FC.EVT_FC_LEFT_DOWN, self.BallHit)
Canvas.Bind(FC.EVT_MOTION, self.OnMove )
Canvas.Bind(FC.EVT_LEFT_UP, self.OnLeftUp )
wx.CallAfter(Canvas.ZoomToBB)
def BallHit(self, object):
print "the ball was clicked"
self.Ball.Moving = True
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
and moves the object it is clicked on
"""
self.SetStatusText("%.4f, %.4f"%tuple(event.Coords))
if self.Ball.Moving:
self.Ball.SetPoint(event.Coords)
self.Canvas.Draw(True)
def OnLeftUp(self, event):
self.Ball.Moving = False
def OnReset(self, event=None):
self.Ball.SetPoint( (5, 52) )
self.Ball.Velocity = np.array((1.5, 0.0))
self.Canvas.Draw(True)
def OnStart(self, event=None):
self.timer.Start(20)
def OnStop(self, event=None):
self.timer.Stop()
def MoveBall(self, event=None):
ball = self.Ball
dt = .1
g = 9.806
m = 1
A = np.pi*(ball.Radius/100)**2 # radius in cm
Cd = 0.47
rho = 1.3
if not ball.Moving: # don't do this if the user is moving it
vel = ball.Velocity
pos = ball.XY
# apply drag
vel -= np.sign(vel) * ((0.5 * Cd * rho * A * vel**2) / m * dt)
# apply gravity
vel[1] -= g * dt
# move the ball
pos += dt * vel
# check if it's on the wall
if pos[1] <= 52. and pos[0] <= 10.:
#reverse velocity
vel[1] *= -1.0
pos[1] = 52.
# check if it's hit the floor
elif pos[1] <= ball.Radius:
#reverse velocity
vel[1] *= -1.0
pos[1] = ball.Radius
self.Ball.SetPoint( pos )
self.Canvas.Draw(True)
wx.GetApp().Yield(onlyIfNeeded=True)
class DemoApp(wx.App):
def OnInit(self):
frame = DrawFrame(None, -1, "Simple Drawing Window",wx.DefaultPosition, (700,700) )
self.SetTopWindow(frame)
return True
if __name__ == "__main__":
app = DemoApp(0)
app.MainLoop()

126
samples/floatcanvas/Chart.py Executable file
View File

@@ -0,0 +1,126 @@
#!/usr/bin/env python
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "White",
).Canvas
# Canvas = FloatCanvas.FloatCanvas(self,-1,
# size = (500,500),
# ProjectionFun = None,
# Debug = 0,
# BackgroundColor = "White",
# )
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
FloatCanvas.EVT_LEFT_DOWN(self.Canvas, self.OnLeft)
# Some default sizes:
self.LineHeight = 1
self.TextWidth = 8
self.SpaceWidth = 1
self.Labels = ["SW Tasks", "Set RX Rf"] + ["A Row Label"]*16
self.NumRows = len(self.Labels)
self.BuildChartBackground()
self.AddLabels()
self.Show()
Canvas.MinScale=28
Canvas.MaxScale=28
Canvas.ZoomToBB()
def BuildChartBackground(self):
Canvas = self.Canvas
top = 0
bottom = -(self.LineHeight * self.NumRows)
width = self.SpaceWidth * 16 + self.TextWidth
# put in the rows:
for i in range(1, self.NumRows+1, 2):
Canvas.AddRectangle((0-self.TextWidth, -i*self.LineHeight),
(width, self.LineHeight),
LineColor = None,
FillColor = "LightGrey",
FillStyle = "Solid",)
# put a dashed line in every 1 unit:
for i in range(16):
Canvas.AddLine(((i*self.SpaceWidth,bottom),(i*self.SpaceWidth,top)),
LineColor = "Black",
LineStyle = "Dot",
# or "Dot", "ShortDash", "LongDash","ShortDash", "DotDash"
LineWidth = 1,)
def AddLabels(self):
Canvas = self.Canvas
for i, label in enumerate(self.Labels):
Canvas.AddScaledText(label,
( -self.TextWidth, -(i+0.2)*self.LineHeight ),
Size = 0.6 * self.LineHeight,
Color = "Black",
BackgroundColor = None,
Family = wx.MODERN,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'tl',
)
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
def OnLeft(self, event):
"""
Prints various info about the state of the canvas to stdout
"""
print "Scale is:", self.Canvas.Scale
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

View File

@@ -0,0 +1,119 @@
#!/usr/bin/env python
"""
This is a little demo of how to make clickable (and changeable) objects with
FloatCanvas
Also an example of constant size, rather than the usual zooming and panning
Developed as an answer to a question on the wxPYhton mailing lilst:
"get panel id while dragging across several panels'
April 5, 2012
"""
import random
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import FloatCanvas as FC
colors = [ (255, 0 , 0 ),
(0 , 255, 0 ),
(0 , 0, 255),
(255, 255, 0 ),
(255, 0, 255),
(0 , 255, 255),
]
class DrawFrame(wx.Frame):
"""
A frame used for the Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
# Add the Canvas
Canvas = FC.FloatCanvas(self,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "Black",
)
self.Canvas = Canvas
self.Canvas.Bind(wx.EVT_SIZE, self.OnSize)
# build the squares:
w = 10
dx = 14
for i in range(9):
for j in range(9):
Rect = Canvas.AddRectangle((i*dx, j*dx), (w, w), FillColor="White", LineStyle = None)
Outline = Canvas.AddRectangle((i*dx, j*dx), (w, w),
FillColor=None,
LineWidth=4,
LineColor='Red',
LineStyle=None)
Rect.indexes = (i,j)
Rect.outline = Outline
Rect.Bind(FC.EVT_FC_LEFT_DOWN, self.SquareHitLeft)
Rect.Bind(FC.EVT_FC_ENTER_OBJECT, self.SquareEnter)
Rect.Bind(FC.EVT_FC_LEAVE_OBJECT, self.SquareLeave)
self.Show()
Canvas.ZoomToBB()
def SquareHitLeft(self, square):
print "square hit:", square.indexes
# set a random color
c = random.sample(colors, 1)[0]
square.SetFillColor( c )
self.Canvas.Draw(True)
def SquareEnter(self, square):
print "entering square:", square.indexes
square.outline.SetLineStyle("Solid")
self.Canvas.Draw(True)
def SquareLeave(self, square):
print "leaving square:", square.indexes
square.outline.SetLineStyle(None)
self.Canvas.Draw(True)
def OnSize(self, event):
"""
re-zooms the canvas to fit the window
"""
print "in OnSize"
self.Canvas.ZoomToBB()
event.Skip()
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

72
samples/floatcanvas/DrawBot.py Executable file
View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python
"""
DrawBot.py
This a a demo of how one can use the FloatCanvas to do a drawing similar to one of the "DrawBot" demos:
http://just.letterror.com/ltrwiki/DrawBot
I think it's easier with FloatCavnas, and you get zoomign and scrolling to boot!
"""
import wx
from math import *
try: # see if there is a local FloatCanvas to use
import sys
sys.path.append("../")
from floatcanvas import NavCanvas, FloatCanvas
print "Using local FloatCanvas"
except ImportError: # Use the wxPython lib one
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
print "Using installed FloatCanvas"
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self,parent, id,title,position,size):
wx.Frame.__init__(self,parent, id,title,position, size)
# Add the Canvas
self.Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "White",
).Canvas
self.Show(True)
self.MakePic()
return None
def MakePic(self):
Canvas = self.Canvas
phi = (sqrt(5) + 1)/2 - 1
oradius = 10.0
for i in xrange(720):
radius = 1.5 * oradius * sin(i * pi/720)
Color = (255*(i / 720.), 255*( i / 720.), 255 * 0.25)
x = oradius + 0.25*i*cos(phi*i*2*pi)
y = oradius + 0.25*i*sin(phi*i*2*pi)
Canvas.AddCircle((x,y),
radius,
LineColor = "Black",
LineWidth = 2,
FillColor = Color,
)
self.Canvas.ZoomToBB()
app = wx.PySimpleApp()
DrawFrame(None, -1, "FloatCanvas Demo App", wx.DefaultPosition, (700,700) )
app.MainLoop()

117
samples/floatcanvas/DrawRect.py Executable file
View File

@@ -0,0 +1,117 @@
#!/usr/bin/env python
"""
A simple demo that shows how to use FloatCanvas to draw rectangles on the screen
Note: this is now broken -- the events are not getting to the Rubber Band Box object.
It should be re-factored to use GUIMode
"""
import wx
## import a local version
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas, Resources, Utilities, GUIMode
#from floatcanvas.Utilities import GUI
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
from wx.lib.floatcanvas.Utilities import GUI
import numpy as N
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self,parent, id,title,position,size):
wx.Frame.__init__(self,parent, id,title,position, size)
self.CreateStatusBar()
# Add the Canvas
NC = NavCanvas.NavCanvas(self,
size= (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
)
self.Canvas = NC.Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
# Add some buttons to the Toolbar
tb = NC.ToolBar
tb.AddSeparator()
ClearButton = wx.Button(tb, wx.ID_ANY, "Clear")
tb.AddControl(ClearButton)
ClearButton.Bind(wx.EVT_BUTTON, self.Clear)
DrawButton = wx.Button(tb, wx.ID_ANY, "StopDrawing")
tb.AddControl(DrawButton)
DrawButton.Bind(wx.EVT_BUTTON, self.SetDraw)
self.DrawButton = DrawButton
tb.Realize()
# Initialize a few values
self.Rects = []
self.RBBoxMode = GUI.RubberBandBox(self.NewRect)
self.Canvas.SetMode(self.RBBoxMode)
self.Canvas.ZoomToBB()
self.Show(True)
return None
def Clear(self, event=None):
self.Rects = []
self.Canvas.ClearAll()
self.Canvas.Draw()
def SetDraw(self, event=None):
label = self.DrawButton.GetLabel()
if label == "Draw":
self.DrawButton.SetLabel("StopDrawing")
self.Canvas.SetMode(self.RBBoxMode)
elif label == "StopDrawing":
self.DrawButton.SetLabel("Draw")
self.Canvas.SetMode(GUIMode.GUIMouse())
else: # huh?
pass
def NewRect(self, rect):
self.Rects.append(self.Canvas.AddRectangle(*rect, LineWidth=4))
self.Canvas.Draw(True)
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.4f, %.4f"%tuple(event.Coords))
event.Skip()
app = wx.PySimpleApp()
DrawFrame(None, -1, "FloatCanvas Rectangle Drawer", wx.DefaultPosition, (700,700) )
app.MainLoop()

84
samples/floatcanvas/GridDemo.py Executable file
View File

@@ -0,0 +1,84 @@
#!/usr/bin/env python
"""
A simple demo to show how to do grids
"""
import wx
try:
# See if there is a local copy
import sys
sys.path.append("../")
from floatcanvas import NavCanvas, FloatCanvas
except ImportError:
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
Point = (45,40)
Box = Canvas.AddCircle(Point,
Diameter = 10,
FillColor = "Black",
LineColor = "Red",
LineWidth = 6)
# Crosses:
Grid = FloatCanvas.DotGrid( Spacing=(1, .5), Size=2, Color="Cyan", Cross=True, CrossThickness=2)
#Dots:
#Grid = FloatCanvas.DotGrid( (0.5, 1), Size=3, Color="Red")
Canvas.GridUnder = Grid
#Canvas.GridOver = Grid
FloatCanvas.EVT_MOTION(Canvas, self.OnMove )
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
app = wx.App(False) # true to get its own output window.
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

View File

@@ -0,0 +1,121 @@
#!/usr/bin/env python
"""
A small demo of how to use Groups of Objects
"""
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
NC = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
)
Canvas = NC.Canvas
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
Point = (45,40)
## create a few Objects:
C = FloatCanvas.Circle((0, 0), 10, FillColor="Red")
R = FloatCanvas.Rectangle((5, 5),(15, 8), FillColor="Blue")
E = FloatCanvas.Ellipse((1.5, 1.5), (12, 8), FillColor="Purple")
C2 = FloatCanvas.Circle((0, 5), 10, FillColor="cyan")
T = FloatCanvas.Text("Group A", (5.5, 5.5), Position="cc", Size = 16, Weight=wx.BOLD, Family=wx.SWISS)
self.GroupA = FloatCanvas.Group((R,C,E))
self.GroupA.AddObjects((C2,T))
Canvas.AddObject(self.GroupA)
## create another Groups of objects
R = FloatCanvas.Rectangle((15, 15),(10, 18), FillColor="orange")
E = FloatCanvas.Ellipse((22, 28), (12, 8), FillColor="yellow")
C = FloatCanvas.Circle((25, 20), 15, FillColor="Green")
C2 = FloatCanvas.Circle((12, 22), 10, FillColor="cyan")
T = FloatCanvas.Text("Group B", (19, 24), Position="cc", Size = 16, Weight=wx.BOLD, Family=wx.SWISS)
self.GroupB = FloatCanvas.Group((R,E,C,C2,T))
Canvas.AddObject(self.GroupB)
self.Groups = {"A":self.GroupA, "B":self.GroupB}
# Add a couple of tools to the Canvas Toolbar
tb = NC.ToolBar
# tb.AddSeparator()
for Group in self.Groups.keys():
Button = wx.Button(tb, wx.ID_ANY, "Remove %s"%Group)
tb.AddControl(Button)
Button.Bind(wx.EVT_BUTTON, lambda evt, group=Group: self.RemoveGroup(evt, group))
Button = wx.Button(tb, wx.ID_ANY, "Replace%s"%Group)
tb.AddControl(Button)
Button.Bind(wx.EVT_BUTTON, lambda evt, group=Group: self.ReplaceGroup(evt, group))
tb.Realize()
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates of the mouse position
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
def RemoveGroup(self, evt, group=""):
print "removing group:", group
G = self.Groups[group]
self.Canvas.RemoveObject(G)
self.Canvas.Draw(Force=True)
def ReplaceGroup(self, evt, group=""):
print "replacing group:", group
G = self.Groups[group]
self.Canvas.AddObject(G)
self.Canvas.Draw(Force=True)
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

View File

@@ -0,0 +1,111 @@
#!/usr/bin/env python
"""
A small demo of how to use Groups of Objects
"""
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
NC = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
)
Canvas = NC.Canvas
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
Point = (45,40)
## create a few Objects:
C = FloatCanvas.Circle((0, 0), 10, FillColor="Red")
R = FloatCanvas.Rectangle((5, 5),(15, 8), FillColor="Blue")
E = FloatCanvas.Ellipse((1.5, 1.5), (12, 8), FillColor="Purple")
C2 = FloatCanvas.Circle((0, 5), 10, FillColor="cyan")
T = FloatCanvas.Text("Group A", (5.5, 5.5), Position="cc", Size = 16, Weight=wx.BOLD, Family=wx.SWISS)
self.GroupA = FloatCanvas.Group((R,C,E))
self.GroupA.AddObjects((C2,T))
Canvas.AddObject(self.GroupA)
## create another Groups of objects
R = FloatCanvas.Rectangle((15, 15),(10, 18), FillColor="orange")
E = FloatCanvas.Ellipse((22, 28), (12, 8), FillColor="yellow")
C = FloatCanvas.Circle((25, 20), 15, FillColor="Green")
C2 = FloatCanvas.Circle((12, 22), 10, FillColor="cyan")
T = FloatCanvas.Text("Group B", (19, 24), Position="cc", Size = 16, Weight=wx.BOLD, Family=wx.SWISS)
self.GroupB = FloatCanvas.Group((R,E,C,C2,T))
Canvas.AddObject(self.GroupB)
self.Groups = {"A":self.GroupA, "B":self.GroupB}
# Add a couple of tools to the Canvas Toolbar
tb = NC.ToolBar
# tb.AddSeparator()
for Group in self.Groups.keys():
Button = wx.Button(tb, wx.ID_ANY, "Hide/Show%s"%Group)
tb.AddControl(Button)
print Group
Button.Bind(wx.EVT_BUTTON, lambda evt, group=Group: self.HideGroup(evt, group))
tb.Realize()
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates of the mouse position
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
def HideGroup(self, evt, group=""):
G = self.Groups[group]
G.Visible = not G.Visible
self.Canvas.Draw(Force=True)
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

102
samples/floatcanvas/Hexagons.py Executable file
View File

@@ -0,0 +1,102 @@
#!/usr/bin/env python
"""
A simple demo to display a lot of hexagons
This was an example someone had on the wxPython-users list
"""
import wx
import wx.lib.colourdb
## import local version:
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
## import installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
NumHexagons = 1000
import numpy as N
from numpy.random import uniform
import random
import time
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
# Add the Canvas
self.Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
ProjectionFun = None,
Debug = 1,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.MakeHexagons()
self.Show(True)
print "Drawing the Hexagons"
self.Canvas.ZoomToBB()
return None
def MakeHexagons(self):
print "Building %i Hexagons"%NumHexagons
# get a list of colors for random colors
wx.lib.colourdb.updateColourDB()
self.colors = wx.lib.colourdb.getColourList()
print "Max colors:", len(self.colors)
Canvas = self.Canvas
D = 1.0
h = D *N.sqrt(3)/2
Hex = N.array(((D , 0),
(D/2 , -h),
(-D/2, -h),
(-D , 0),
(-D/2, h),
(D/2 , h),
))
Centers = uniform(-100, 100, (NumHexagons, 2))
for center in Centers:
# scale the hexagon
Points = Hex * uniform(5,20)
#print Points
# shift the hexagon
Points = Points + center
#print Points
cf = random.randint(0,len(self.colors)-1)
#cf = 55
H = Canvas.AddPolygon(Points, LineColor = None, FillColor = self.colors[cf])
#print "BrushList is: %i long"%len(H.BrushList)
H.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.HexHit)
print "BrushList is: %i long"%len(H.BrushList)
def HexHit(self, Hex):
print "A %s Hex was hit, obj ID: %i"%(Hex.FillColor, id(Hex))
app = wx.App(False)
DrawFrame(None, -1, "FloatCanvas Demo App", wx.DefaultPosition, (700,700) )
app.MainLoop()

77
samples/floatcanvas/Map.py Executable file
View File

@@ -0,0 +1,77 @@
#!/usr/bin/env python
TestFileName = "../data/TestMap.png"
import wx
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
NC = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "White",
)
self.Canvas = NC.Canvas
self.LoadMap(TestFileName)
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
self.Show()
self.Canvas.ZoomToBB()
def LoadMap(self, filename):
Image = wx.Image(filename)
self.Canvas.AddScaledBitmap(Image, (0,0), Height = Image.GetSize()[1], Position = "tl")
self.Canvas.AddPoint((0,0), Diameter=3)
self.Canvas.AddText("(0,0)", (0,0), Position="cl")
p = (Image.GetSize()[0],-Image.GetSize()[1])
self.Canvas.AddPoint(p, Diameter=3)
self.Canvas.AddText("(%i,%i)"%p, p, Position="cl")
self.Canvas.MinScale = 0.15
self.Canvas.MaxScale = 1.0
def Binding(self, event):
print "Writing a png file:"
self.Canvas.SaveAsImage("junk.png")
print "Writing a jpeg file:"
self.Canvas.SaveAsImage("junk.jpg",wx.BITMAP_TYPE_JPEG)
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
And moves a point if there is one selected
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

View File

@@ -0,0 +1,83 @@
#!/usr/bin/env python
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
Point = (45,40)
Text = Canvas.AddScaledText("A String",
Point,
20,
Color = "Black",
BackgroundColor = None,
Family = wx.ROMAN,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'bl',
InForeground = False)
Text.MinFontSize = 4 # the default is 1
Text.DisappearWhenSmall = False #the default is True
Rect = Canvas.AddRectangle((50, 20), (40,10), FillColor="Red", LineStyle = None)
Rect.MinSize = 4 # default is 1
Rect.DisappearWhenSmall = False # defualt is True
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

381
samples/floatcanvas/MiniDemo.py Executable file
View File

@@ -0,0 +1,381 @@
#!/usr/bin/env python
import wx
## import local version:
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
## import installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
import wx.lib.colourdb
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
## Set up the MenuBar
MenuBar = wx.MenuBar()
file_menu = wx.Menu()
item = file_menu.Append(wx.ID_ANY, "&Close","Close this frame")
self.Bind(wx.EVT_MENU, self.OnQuit, item)
MenuBar.Append(file_menu, "&File")
draw_menu = wx.Menu()
item = draw_menu.Append(wx.ID_ANY, "&Draw Test","Run a test of drawing random components")
self.Bind(wx.EVT_MENU,self.DrawTest, item)
item = draw_menu.Append(wx.ID_ANY, "&Move Test","Run a test of moving stuff in the background")
self.Bind(wx.EVT_MENU, self.MoveTest, item)
item = draw_menu.Append(wx.ID_ANY, "&Clear","Clear the Canvas")
self.Bind(wx.EVT_MENU,self.Clear, item)
MenuBar.Append(draw_menu, "&Draw")
view_menu = wx.Menu()
item = view_menu.Append(wx.ID_ANY, "Zoom to &Fit","Zoom to fit the window")
self.Bind(wx.EVT_MENU,self.ZoomToFit, item)
MenuBar.Append(view_menu, "&View")
help_menu = wx.Menu()
item = help_menu.Append(wx.ID_ANY, "&About",
"More information About this program")
self.Bind(wx.EVT_MENU, self.OnAbout, item)
MenuBar.Append(help_menu, "&Help")
self.SetMenuBar(MenuBar)
self.CreateStatusBar()
self.SetStatusText("")
wx.EVT_CLOSE(self, self.OnCloseWindow)
# Add the Canvas
self.Canvas = NavCanvas.NavCanvas(self,
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Show(True)
# get a list of colors for random colors
wx.lib.colourdb.updateColourDB()
self.colors = wx.lib.colourdb.getColourList()
self.LineStyles = FloatCanvas.DrawObject.LineStyleList.keys()
return None
def OnAbout(self, event):
dlg = wx.MessageDialog(self, "This is a small program to demonstrate\n"
"the use of the FloatCanvas\n",
"About Me", wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def ZoomToFit(self,event):
self.Canvas.ZoomToBB()
def Clear(self,event = None):
self.Canvas.ClearAll()
self.Canvas.Draw()
def OnQuit(self,event):
self.Close(True)
def OnCloseWindow(self, event):
self.Destroy()
def DrawTest(self,event):
wx.GetApp().Yield()
import random
import numpy.random as RandomArray
Range = (-10,10)
Canvas = self.Canvas
Canvas.ClearAll()
# Set some zoom limits:
self.Canvas.MinScale = 15.0
self.Canvas.MaxScale = 500.0
#### Draw a few Random Objects ####
# Rectangles
for i in range(5):
xy = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
lw = random.randint(1,5)
cf = random.randint(0,len(self.colors)-1)
h = random.randint(1,5)
w = random.randint(1,5)
Canvas.AddRectangle(xy, (h,w),
LineWidth = lw,
FillColor = self.colors[cf])
# Ellipses
for i in range(5):
xy = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
lw = random.randint(1,5)
cf = random.randint(0,len(self.colors)-1)
h = random.randint(1,5)
w = random.randint(1,5)
Canvas.AddEllipse(xy, (h,w),
LineWidth = lw,
FillColor = self.colors[cf])
# Circles
for i in range(5):
point = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
D = random.randint(1,5)
lw = random.randint(1,5)
cf = random.randint(0,len(self.colors)-1)
cl = random.randint(0,len(self.colors)-1)
Canvas.AddCircle(point, D,
LineWidth = lw,
LineColor = self.colors[cl],
FillColor = self.colors[cf])
Canvas.AddText("Circle # %i"%(i),
point,
Size = 12,
Position = "cc")
# Lines
for i in range(5):
points = []
for j in range(random.randint(2,10)):
point = (random.randint(Range[0],Range[1]),random.randint(Range[0],Range[1]))
points.append(point)
lw = random.randint(1,10)
cf = random.randint(0,len(self.colors)-1)
cl = random.randint(0,len(self.colors)-1)
Canvas.AddLine(points, LineWidth = lw, LineColor = self.colors[cl])
# Polygons
for i in range(3):
points = []
for j in range(random.randint(2,6)):
point = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
points.append(point)
lw = random.randint(1,6)
cf = random.randint(0,len(self.colors)-1)
cl = random.randint(0,len(self.colors)-1)
Canvas.AddPolygon(points,
LineWidth = lw,
LineColor = self.colors[cl],
FillColor = self.colors[cf],
FillStyle = 'Solid')
self.Canvas.ZoomToBB()
def MoveTest(self,event=None):
print "Running: TestHitTestForeground"
wx.GetApp().Yield()
self.UnBindAllMouseEvents()
Canvas = self.Canvas
Canvas.ClearAll()
# Clear the zoom limits:
self.Canvas.MinScale = None
self.Canvas.MaxScale = None
Canvas.SetProjectionFun(None)
#Add a Hitable rectangle
w,h = 60, 20
dx = 80
dy = 40
x,y = 20, 20
color = "Red"
R = Canvas.AddRectangle((x,y), (w,h),
LineWidth = 2,
FillColor = color
)
R.Name = color + "Rectangle"
Canvas.AddText(R.Name, (x, y+h), Position = "tl")
## A set of Rectangles that move together
## NOTE: In a real app, it might be better to create a new
## custom FloatCanvas DrawObject
self.MovingRects = []
x += dx
color = "LightBlue"
R = Canvas.AddRectangle((x,y), (w/2, h/2),
LineWidth = 2,
FillColor = color)
R.HitFill = True
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectMoveLeft)
L = Canvas.AddText("Left", (x + w/4, y + h/4),
Position = "cc")
self.MovingRects.extend( (R,L) )
x += w/2
R = Canvas.AddRectangle((x, y), (w/2, h/2),
LineWidth = 2,
FillColor = color)
R.HitFill = True
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectMoveRight)
L = Canvas.AddText("Right", (x + w/4, y + h/4),
Position = "cc")
self.MovingRects.extend( (R,L) )
x -= w/2
y += h/2
R = Canvas.AddRectangle((x, y), (w/2, h/2),
LineWidth = 2,
FillColor = color)
R.HitFill = True
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectMoveUp)
L = Canvas.AddText("Up", (x + w/4, y + h/4),
Position = "cc")
self.MovingRects.extend( (R,L) )
x += w/2
R = Canvas.AddRectangle((x, y), (w/2, h/2),
LineWidth = 2,
FillColor = color)
R.HitFill = True
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectMoveDown)
L = Canvas.AddText("Down", (x + w/4, y + h/4),
Position = "cc")
self.MovingRects.extend( (R,L) )
self.Canvas.ZoomToBB()
def RectMoveLeft(self,Object):
self.MoveRects("left")
def RectMoveRight(self,Object):
self.MoveRects("right")
def RectMoveUp(self,Object):
self.MoveRects("up")
def RectMoveDown(self,Object):
self.MoveRects("down")
def MoveRects(self, Dir):
for Object in self.MovingRects:
X,Y = Object.XY
if Dir == "left": X -= 10
elif Dir == "right": X += 10
elif Dir == "up": Y += 10
elif Dir == "down": Y -= 10
Object.SetPoint((X,Y))
self.Canvas.Draw(True)
def UnBindAllMouseEvents(self):
## Here is how you catch FloatCanvas mouse events
FloatCanvas.EVT_LEFT_DOWN(self.Canvas, None )
FloatCanvas.EVT_LEFT_UP(self.Canvas, None )
FloatCanvas.EVT_LEFT_DCLICK(self.Canvas, None)
FloatCanvas.EVT_MIDDLE_DOWN(self.Canvas, None )
FloatCanvas.EVT_MIDDLE_UP(self.Canvas, None )
FloatCanvas.EVT_MIDDLE_DCLICK(self.Canvas, None )
FloatCanvas.EVT_RIGHT_DOWN(self.Canvas, None )
FloatCanvas.EVT_RIGHT_UP(self.Canvas, None )
FloatCanvas.EVT_RIGHT_DCLICK(self.Canvas, None )
FloatCanvas.EVT_MOUSEWHEEL(self.Canvas, None )
self.EventsAreBound = False
class DemoApp(wx.App):
"""
How the demo works:
Under the Draw menu, there are three options:
*Draw Test: will put up a picture of a bunch of randomly generated
objects, of each kind supported.
*Draw Map: will draw a map of the world. Be patient, it is a big map,
with a lot of data, and will take a while to load and draw (about 10 sec
on my 450Mhz PIII). Redraws take about 2 sec. This demonstrates how the
performance is not very good for large drawings.
*Clear: Clears the Canvas.
Once you have a picture drawn, you can zoom in and out and move about
the picture. There is a tool bar with three tools that can be
selected.
The magnifying glass with the plus is the zoom in tool. Once selected,
if you click the image, it will zoom in, centered on where you
clicked. If you click and drag the mouse, you will get a rubber band
box, and the image will zoom to fit that box when you release it.
The magnifying glass with the minus is the zoom out tool. Once selected,
if you click the image, it will zoom out, centered on where you
clicked. (note that this takes a while when you are looking at the map,
as it has a LOT of lines to be drawn. The image is double buffered, so
you don't see the drawing in progress)
The hand is the move tool. Once selected, if you click and drag on the
image, it will move so that the part you clicked on ends up where you
release the mouse. Nothing is changed while you are dragging. The
drawing is too slow for that.
I'd like the cursor to change as you change tools, but the stock
wx.Cursors didn't include anything I liked, so I stuck with the
pointer. Please let me know if you have any nice cursor images for me to
use.
Any bugs, comments, feedback, questions, and especially code are welcome:
-Chris Barker
Chris.Barker@noaa.gov
"""
def OnInit(self):
frame = DrawFrame(None, wx.ID_ANY,
title = "FloatCanvas Demo App",
size = (700,700) )
self.SetTopWindow(frame)
return True
app = DemoApp(False)
app.MainLoop()

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env python
"""
Small demo of catching Mouse events using just FloatCanvas, rather than
NavCanvas
"""
import wx
app = wx.App(0)
try:
# See if there is a local copy
import sys
sys.path.append("../")
from floatcanvas import NavCanvas, FloatCanvas, GUIMode
except ImportError:
from wx.lib.floatcanvas import NavCanvas, FloatCanvas, GUIMode
class TestFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.canvas =FloatCanvas.FloatCanvas(self, BackgroundColor = "DARK SLATE BLUE")
# Layout
MainSizer = wx.BoxSizer(wx.VERTICAL)
MainSizer.Add(self.canvas, 4, wx.EXPAND)
self.SetSizer(MainSizer)
self.canvas.Bind(FloatCanvas.EVT_LEFT_DOWN, self.OnLeftDown)
self.canvas.AddRectangle((10,10), (100, 20), FillColor="red")
self.canvas.SetMode(GUIMode.GUIMouse(self.canvas))
wx.CallAfter(self.canvas.ZoomToBB)
def OnLeftDown(self, event):
print 'Left Button clicked at:', event.Coords
frame = TestFrame(None, title="Mouse Event Tester")
#self.SetTopWindow(frame)
frame.Show(True)
app.MainLoop()

View File

@@ -0,0 +1,281 @@
#!/usr/bin/env python
"""
This is a small demo, showing how to make an object that can be moved around.
It also contains a simple prototype for a "Connector" object
-- a line connecting two other objects
"""
import wx
#ver = 'local'
ver = 'installed'
if ver == 'installed': ## import the installed version
from wx.lib.floatcanvas import NavCanvas, Resources
from wx.lib.floatcanvas import FloatCanvas as FC
print "using installed version:", wx.lib.floatcanvas.__version__
elif ver == 'local':
## import a local version
import sys
sys.path.append("..")
from floatcanvas import NavCanvas, Resources
from floatcanvas import FloatCanvas as FC
from floatcanvas.Utilities import BBox
import numpy as N
## here we create some new mixins:
class MovingObjectMixin:
"""
Methods required for a Moving object
"""
def GetOutlinePoints(self):
BB = self.BoundingBox
OutlinePoints = N.array( ( (BB[0,0], BB[0,1]),
(BB[0,0], BB[1,1]),
(BB[1,0], BB[1,1]),
(BB[1,0], BB[0,1]),
)
)
return OutlinePoints
class ConnectorObjectMixin:
"""
Mixin class for DrawObjects that can be connected with lines
NOte that this versionony works for Objects that have an "XY" attribute:
that is, one that is derived from XHObjectMixin.
"""
def GetConnectPoint(self):
return self.XY
class MovingBitmap(FC.ScaledBitmap, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
pass
class MovingCircle(FC.Circle, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
pass
class MovingArc(FC.Arc, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
pass
class ConnectorLine(FC.LineOnlyMixin, FC.DrawObject,):
"""
A Line that connects two objects -- it uses the objects to get its coordinates
"""
##fixme: this should be added to the Main FloatCanvas Objects some day.
def __init__(self,
Object1,
Object2,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 1,
InForeground = False):
FC.DrawObject.__init__(self, InForeground)
self.Object1 = Object1
self.Object2 = Object2
self.LineColor = LineColor
self.LineStyle = LineStyle
self.LineWidth = LineWidth
self.CalcBoundingBox()
self.SetPen(LineColor,LineStyle,LineWidth)
self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
def CalcBoundingBox(self):
self.BoundingBox = BBox.fromPoints((self.Object1.GetConnectPoint(),
self.Object2.GetConnectPoint()) )
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
Points = N.array( (self.Object1.GetConnectPoint(),
self.Object2.GetConnectPoint()) )
Points = WorldToPixel(Points)
dc.SetPen(self.Pen)
dc.DrawLines(Points)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.DrawLines(Points)
class TriangleShape1(FC.Polygon, MovingObjectMixin):
def __init__(self, XY, L):
"""
An equilateral triangle object
XY is the middle of the triangle
L is the length of one side of the Triangle
"""
XY = N.asarray(XY)
XY.shape = (2,)
Points = self.CompPoints(XY, L)
FC.Polygon.__init__(self, Points,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 2,
FillColor = "Red",
FillStyle = "Solid")
## Override the default OutlinePoints
def GetOutlinePoints(self):
return self.Points
def CompPoints(self, XY, L):
c = L/ N.sqrt(3)
Points = N.array(((0, c),
( L/2.0, -c/2.0),
(-L/2.0, -c/2.0)),
N.float_)
Points += XY
return Points
class DrawFrame(wx.Frame):
"""
A simple frame used for the Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
Canvas.Bind(FC.EVT_MOTION, self.OnMove )
Canvas.Bind(FC.EVT_LEFT_UP, self.OnLeftUp )
Points = N.array(((0,0),
(1,0),
(0.5, 1)),
N.float)
data = (( (0,0), 1),
( (3,3), 2),
( (-2,3), 2.5 ),
)
for p, L in data:
Tri = TriangleShape1(p, 1)
Canvas.AddObject(Tri)
Tri.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
Circle = MovingCircle( (1, 3), 2, FillColor="Blue")
Canvas.AddObject(Circle)
Circle.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
Bitmaps = []
## create the bitmaps first
for Point in ((1,1), (-4,3)):
Bitmaps.append(MovingBitmap(Resources.getMondrianImage(),
Point,
Height=1,
Position='cc')
)
Line = ConnectorLine(Bitmaps[0], Bitmaps[1], LineWidth=3, LineColor="Red")
Canvas.AddObject(Line)
## then add them to the Canvas, so they are on top of the line
for bmp in Bitmaps:
Canvas.AddObject(bmp)
bmp.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
A = MovingArc((-5, 0),(-2, 2),(-5, 2), LineColor="Red", LineWidth=2)
self.Canvas.AddObject(A)
A.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
self.Show(True)
self.Canvas.ZoomToBB()
self.MoveObject = None
self.Moving = False
return None
def ObjectHit(self, object):
if not self.Moving:
self.Moving = True
self.StartPoint = object.HitCoordsPixel
self.StartObject = self.Canvas.WorldToPixel(object.GetOutlinePoints())
self.MoveObject = None
self.MovingObject = object
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
and moves the object it is clicked on
"""
self.SetStatusText("%.4f, %.4f"%tuple(event.Coords))
if self.Moving:
dxy = event.GetPosition() - self.StartPoint
# Draw the Moving Object:
dc = wx.ClientDC(self.Canvas)
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetLogicalFunction(wx.XOR)
if self.MoveObject is not None:
dc.DrawPolygon(self.MoveObject)
self.MoveObject = self.StartObject + dxy
dc.DrawPolygon(self.MoveObject)
def OnLeftUp(self, event):
if self.Moving:
self.Moving = False
if self.MoveObject is not None:
dxy = event.GetPosition() - self.StartPoint
dxy = self.Canvas.ScalePixelToWorld(dxy)
self.MovingObject.Move(dxy)
self.MoveTri = None
self.Canvas.Draw(True)
if __name__ == "__main__":
app = wx.PySimpleApp(0)
DrawFrame(None, -1, "FloatCanvas Moving Object App", wx.DefaultPosition, (700,700) )
app.MainLoop()

238
samples/floatcanvas/MovingPlot.py Executable file
View File

@@ -0,0 +1,238 @@
#!/usr/bin/env python
"""
A small test app that uses FloatCanvas to draw a plot, and have an
efficient moving line on it.
"""
import wx
import numpy as N
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
## Set up the MenuBar
MenuBar = wx.MenuBar()
file_menu = wx.Menu()
item = file_menu.Append(wx.ID_ANY, "E&xit","Terminate the program")
self.Bind(wx.EVT_MENU, self.OnQuit, item)
MenuBar.Append(file_menu, "&File")
draw_menu = wx.Menu()
item = draw_menu.Append(wx.ID_ANY, "&Run","Run the test")
self.Bind(wx.EVT_MENU, self.RunTest, item)
item = draw_menu.Append(wx.ID_ANY, "&Stop","Stop the test")
self.Bind(wx.EVT_MENU, self.Stop, item)
MenuBar.Append(draw_menu, "&Plot")
help_menu = wx.Menu()
item = help_menu.Append(wx.ID_ANY, "&About",
"More information About this program")
self.Bind(wx.EVT_MENU, self.OnAbout, item)
MenuBar.Append(help_menu, "&Help")
self.SetMenuBar(MenuBar)
self.CreateStatusBar()
self.SetStatusText("")
wx.EVT_CLOSE(self, self.OnCloseWindow)
# Add the Canvas
NC = NavCanvas.NavCanvas(self ,wx.ID_ANY ,(500,300),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "WHITE"
)
self.Canvas = NC.Canvas
self.Canvas.NumBetweenBlits = 1000
# Add a couple of tools to the Canvas Toolbar
tb = NC.ToolBar
tb.AddSeparator()
StopButton = wx.Button(tb, wx.ID_ANY, "Stop")
tb.AddControl(StopButton)
StopButton.Bind(wx.EVT_BUTTON, self.Stop)
PlayButton = wx.Button(tb, wx.ID_ANY, "Run")
tb.AddControl(PlayButton)
PlayButton.Bind(wx.EVT_BUTTON, self.RunTest)
tb.Realize()
self.Show(True)
self.timer = None
self.DrawAxis()
return None
def OnAbout(self, event):
dlg = wx.MessageDialog(self, "This is a small program to demonstrate\n"
"the use of the FloatCanvas\n"
"for simple plotting",
"About Me", wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def ZoomToFit(self,event):
self.Canvas.ZoomToBB()
def OnQuit(self,event):
self.Close(True)
def OnCloseWindow(self, event):
self.Destroy()
def DrawAxis(self):
Canvas = self.Canvas
# Draw the Axis
# Note: the AddRectangle Parameters all have sensible
# defaults. I've put them all here explicitly, so you can see
# what the options are.
self.Canvas.AddRectangle((0, -1.1),
(2*N.pi, 2.2),
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 1,
FillColor = None,
FillStyle = "Solid",
InForeground = 0)
for tic in N.arange(7):
self.Canvas.AddText("%1.1f"%tic,
(tic,-1.1),
Position = 'tc')
for tic in N.arange(-1, 1.1, 0.5):
self.Canvas.AddText("%1.1f"%tic,
(0,tic),
Position = 'cr')
# Add a phantom rectangle to get the bounding box right
# (the bounding box doesn't get unscaled text right)
self.Canvas.AddRectangle((-0.7, -1.5), (7, 3), LineColor = None)
Canvas.ZoomToBB()
Canvas.Draw()
def Stop(self,event):
if self.timer:
self.timer.Stop()
def OnTimer(self,event):
self.count += .1
self.data1[:,1] = N.sin(self.time+self.count) #fake move
self.line.SetPoints(self.data1)
self.Canvas.Draw()
def RunTest(self,event = None):
self.n = 100
self.dT = 0.05
self.time = 2.0*N.pi*N.arange(100)/100.0
self.data1 = 1.0*N.ones((100,2))
self.data1[:,0] = self.time
self.data1[:,1] = N.sin(self.time)
Canvas = self.Canvas
self.Canvas.ClearAll()
self.DrawAxis()
self.line = Canvas.AddLine(self.data1,
LineColor = "Red",
LineStyle = "Solid",
LineWidth = 2,
InForeground = 1)
self.Canvas.Draw()
self.timerID = wx.NewId()
self.timer = wx.Timer(self,self.timerID)
wx.EVT_TIMER(self,self.timerID,self.OnTimer)
self.count = 0
self.timer.Start(int(self.dT*1000))
class DemoApp(wx.App):
"""
How the demo works:
Either under the Draw menu, or on the toolbar, you can push Run and Stop
"Run" start an oscilloscope like display of a moving sine curve
"Stop" stops it.
While the plot os running (or not) you can zoom in and out and move
about the picture. There is a tool bar with three tools that can be
selected.
The magnifying glass with the plus is the zoom in tool. Once selected,
if you click the image, it will zoom in, centered on where you
clicked. If you click and drag the mouse, you will get a rubber band
box, and the image will zoom to fit that box when you release it.
The magnifying glass with the minus is the zoom out tool. Once selected,
if you click the image, it will zoom out, centered on where you
clicked.
The hand is the move tool. Once selected, if you click and drag on
the image, it will move so that the part you clicked on ends up
where you release the mouse. Nothing is changed while you are
dragging, but you can see the outline of the former picture.
I'd like the cursor to change as you change tools, but the stock
wx.Cursors didn't include anything I liked, so I stuck with the
pointer. Please let me know if you have any nice cursor images for me to
use.
Any bugs, comments, feedback, questions, and especially code are welcome:
-Chris Barker
Chris.Barker@noaa.gov
"""
def OnInit(self):
wx.InitAllImageHandlers()
frame = DrawFrame(None, wx.ID_ANY,
title = "Plotting Test",
size = (700,400) )
self.SetTopWindow(frame)
return True
if __name__ == "__main__":
app = DemoApp(0)
app.MainLoop()

View File

@@ -0,0 +1,189 @@
#!/usr/bin/env python
"""
This is a small demo, showing how to make an object that can be moved around.
"""
import wx
#ver = 'local'
ver = 'installed'
if ver == 'installed': ## import the installed version
from wx.lib.floatcanvas import NavCanvas, Resources
from wx.lib.floatcanvas import FloatCanvas as FC
print "using installed version:", wx.lib.floatcanvas.__version__
elif ver == 'local':
## import a local version
import sys
sys.path.append("..")
from floatcanvas import NavCanvas, Resources
from floatcanvas import FloatCanvas as FC
import numpy as N
## here we create a new DrawObject:
## code borrowed and adapted from Werner Bruhin
class ShapeMixin:
"""
just here for added features later
"""
def __init__(self):
pass
class TriangleShape1(FC.Polygon, ShapeMixin):
def __init__(self, XY, L):
"""
An equilateral triangle object
XY is the middle of the triangle
L is the length of one side of the Triangle
"""
XY = N.asarray(XY)
XY.shape = (2,)
Points = self.CompPoints(XY, L)
FC.Polygon.__init__(self, Points,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 2,
FillColor = "Red",
FillStyle = "Solid")
ShapeMixin.__init__(self)
def CompPoints(self, XY, L):
c = L/ N.sqrt(3)
Points = N.array(((0, c),
( L/2.0, -c/2.0),
(-L/2.0, -c/2.0)),
N.float_)
Points += XY
return Points
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self,parent, id,title,position,size):
wx.Frame.__init__(self,parent, id,title,position, size)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
Canvas.Bind(FC.EVT_MOTION, self.OnMove )
Canvas.Bind(FC.EVT_LEFT_UP, self.OnLeftUp )
Canvas.AddRectangle((-5,-5),
(10,10),
LineColor = "Red",
LineStyle = "Solid",
LineWidth = 2,
FillColor = "CYAN",
FillStyle = "Solid")
Points = N.array(((0,0),
(1,0),
(0.5, 1)),
N.float_)
data = (( (0,0), 1),
( (3,3), 2),
( (-2,3), 2.5 ),
)
for p, L in data:
Tri = TriangleShape1(p, 1)
Canvas.AddObject(Tri)
Tri.Bind(FC.EVT_FC_LEFT_DOWN, self.TriHit)
self.MoveTri = None
self.Show(True)
self.Canvas.ZoomToBB()
self.Moving = False
return None
def TriHit(self, object):
print "In TriHit"
if not self.Moving:
self.Moving = True
self.StartPoint = object.HitCoordsPixel
self.StartTri = self.Canvas.WorldToPixel(object.Points)
self.MoveTri = None
self.MovingTri = object
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
And moves the triangle it it is clicked on
"""
self.SetStatusText("%.4f, %.4f"%tuple(event.Coords))
if self.Moving:
dxy = event.GetPosition() - self.StartPoint
# Draw the Moving Triangle:
dc = wx.ClientDC(self.Canvas)
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetLogicalFunction(wx.XOR)
if self.MoveTri is not None:
dc.DrawPolygon(self.MoveTri)
self.MoveTri = self.StartTri + dxy
dc.DrawPolygon(self.MoveTri)
def OnLeftUp(self, event):
if self.Moving:
self.Moving = False
if self.MoveTri is not None:
dxy = event.GetPosition() - self.StartPoint
dxy = self.Canvas.ScalePixelToWorld(dxy)
self.MovingTri.Move(dxy) ## The Move function has jsut been added
## to the FloatCanvas PointsObject
## It does the next three lines for you.
#self.Tri.Points += dxy
#self.Tri.BoundingBox += dxy
#self.Canvas.BoundingBoxDirty = True
self.MoveTri = None
self.Canvas.Draw(True)
app = wx.PySimpleApp(0)
DrawFrame(None, -1, "FloatCanvas TextBox Test App", wx.DefaultPosition, (700,700) )
app.MainLoop()

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -0,0 +1,93 @@
#!/usr/bin/env python
"""
A simple example of how to use FloatCanvas by itself, without the NavCanvas toolbar
"""
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = FloatCanvas.FloatCanvas(self,
size = (500,500),
BackgroundColor = "DARK SLATE BLUE",
)
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
Point = (45,40)
Box = Canvas.AddScaledTextBox("A Two Line\nString",
Point,
2,
Color = "Black",
BackgroundColor = None,
LineColor = "Red",
LineStyle = "Solid",
LineWidth = 1,
Width = None,
PadSize = 5,
Family = wx.ROMAN,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'br',
Alignment = "left",
InForeground = False)
Box.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.Binding)
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
def Binding(self, event):
print "Writing a png file:"
self.Canvas.SaveAsImage("junk.png")
print "Writing a jpeg file:"
self.Canvas.SaveAsImage("junk.jpg",wx.BITMAP_TYPE_JPEG)
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

43
samples/floatcanvas/NonGUI.py Executable file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env python
"""
Demo of a FloatCanvas App that will create an image, without
actually showing anything on screen. It seems to work, but you do need
to have an X-server running on *nix for this to work.
Note: you need to specify the size in the FloatCanvas Constructor.
hmm -- I wonder if you'd even need the frame?
"""
import wx
## import the installed version
from wx.lib.floatcanvas import FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
app = wx.PySimpleApp()
f = wx.Frame(None)
Canvas = FloatCanvas.FloatCanvas(f,
BackgroundColor = "Cyan",
size=(500,500)
)
Canvas.AddRectangle((0,0), (16,20))
Canvas.AddRectangle((1,1), (6,8.5))
Canvas.AddRectangle((9,1), (6,8.5))
Canvas.AddRectangle((9,10.5), (6,8.5))
Canvas.AddRectangle((1,10.5), (6,8.5))
Canvas.ZoomToBB()
print "Saving the image:", "junk.png"
Canvas.SaveAsImage("junk.png")

View File

@@ -0,0 +1,142 @@
#!/usr/bin/env python
"""
A simple demo to show how to "Overlays": i.e. drawing something
on top of eveything else on the Canvas, relative to window coords,
rather than screen coords.
This method uses the "GridOver" object in the FloatCanvas
- it was orginally dsigend for girds, graticule,s etc. that
are always drawn regardless of zoom, pan, etc, but it works
for overlays too.
"""
import wx
try:
# See if there is a local copy
import sys
sys.path.append("../")
from floatcanvas import NavCanvas, FloatCanvas
except ImportError:
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
class TextOverlay(FloatCanvas.Text):
"""
An example of an Overlay object:
all it needs is a new _Draw method.
NOTE: you may want to get fancier with this,
deriving from ScaledTextBox
"""
def __init__(self,
String,
xy,
Size = 24,
Color = "Black",
BackgroundColor = None,
Family = wx.MODERN,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Font = None):
FloatCanvas.Text.__init__(self,
String,
xy,
Size = Size,
Color = Color,
BackgroundColor = BackgroundColor,
Family = Family,
Style = Style,
Weight = Weight,
Underlined = Underlined,
Font = Font)
def _Draw(self, dc, Canvas):
"""
_Draw method for Overlay
note: this is a differeent signarture than the DrawObject Draw
"""
dc.SetFont(self.Font)
dc.SetTextForeground(self.Color)
if self.BackgroundColor:
dc.SetBackgroundMode(wx.SOLID)
dc.SetTextBackground(self.BackgroundColor)
else:
dc.SetBackgroundMode(wx.TRANSPARENT)
## maybe inpliment this...
#if self.TextWidth is None or self.TextHeight is None:
# (self.TextWidth, self.TextHeight) = dc.GetTextExtent(self.String)
#XY = self.ShiftFun(XY[0], XY[1], self.TextWidth, self.TextHeight)
dc.DrawTextPoint(self.String, self.XY)
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
Point = (45,40)
Box = Canvas.AddCircle(Point,
Diameter = 10,
FillColor = "Cyan",
LineColor = "Red",
LineWidth = 6)
Canvas.GridOver = TextOverlay("Some Text",
(20,20),
Size = 48,
Color = "Black",
BackgroundColor = 'Pink',
)
FloatCanvas.EVT_MOTION(Canvas, self.OnMove )
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
app = wx.App(False) # true to get its own output window.
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

91
samples/floatcanvas/PieChart.py Executable file
View File

@@ -0,0 +1,91 @@
#!/usr/bin/env python
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
from wx.lib.floatcanvas.SpecialObjects import PieChart
## import a local version
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
#from floatcanvas.SpecialObjects import PieChart
import numpy as N
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
Values = (10,10,10)
Colors = ('Red', 'Blue', 'Green')
Pie1 = PieChart(N.array((0, 0)), 10, Values, Colors, Scaled=False)
Canvas.AddObject(Pie1)
Values = (10, 5, 5)
Pie2 = PieChart(N.array((40, 0)), 10, Values, Colors)
Canvas.AddObject(Pie2)
# test default colors
Values = (10, 15, 12, 24, 6, 10, 13, 11, 9, 13, 15, 12)
Pie3 = PieChart(N.array((20, 20)), 10, Values, LineColor="Black")
Canvas.AddObject(Pie3)
# missng slice!
Values = (10, 15, 12, 24)
Colors = ('Red', 'Blue', 'Green', None)
Pie4 = PieChart(N.array((0, -15)), 10, Values, Colors, LineColor="Black")
Canvas.AddObject(Pie4)
# Test the styles
Values = (10, 12, 14)
Styles = ("Solid", "CrossDiagHatch","CrossHatch")
Colors = ('Red', 'Blue', 'Green')
Pie4 = PieChart(N.array((20, -20)), 10, Values, Colors, Styles)
Canvas.AddObject(Pie2)
Pie1.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.Pie1Hit)
Pie2.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.Pie2Hit)
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
self.Show()
Canvas.ZoomToBB()
def Pie1Hit(self, obj):
print "Pie1 hit!"
def Pie2Hit(self, obj):
print "Pie2 hit!"
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2g, %.2g"%tuple(event.Coords))
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

View File

@@ -0,0 +1,150 @@
#!/usr/bin/env python
"""
A simple demo to show how to drw a bitmap on top of the Canvas at given pixel coords.
"""
import wx
import numpy as np
try:
# See if there is a local copy
import sys
sys.path.append("../")
from floatcanvas import NavCanvas, FloatCanvas
except ImportError:
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
FC = FloatCanvas
class PixelBitmap:
"""
An unscaled bitmap that can be put on top of the canvas using:
Canvas.GridOver = MyPixelBitmap
It will always be drawn on top of everything else, and be positioned
according to pixel coordinates on teh screen, regardless of zoom and
pan position.
"""
def __init__(self, Bitmap, XY, Position = 'tl'):
"""
PixelBitmap (Bitmap, XY, Position='tl')
Bitmap is a wx.Bitmap or wx.Image
XY is the (x,y) location to place the bitmap, in pixel coordinates
Position indicates from where in the window the position is relative to:
'tl' indicated the position from the top left the the window (the detault)
'br' the bottom right
'cr the center right, etc.
"""
if type(Bitmap) == wx._gdi.Bitmap:
self.Bitmap = Bitmap
elif type(Bitmap) == wx._core.Image:
self.Bitmap = wx.BitmapFromImage(Bitmap)
else:
raise FC.FloatCanvasError("PixelBitmap takes only a wx.Bitmap or a wx.Image as input")
self.XY = np.asarray(XY, dtype=np.int).reshape((2,))
self.Position = Position
(self.Width, self.Height) = self.Bitmap.GetWidth(), self.Bitmap.GetHeight()
self.ShiftFun = FC.TextObjectMixin.ShiftFunDict[Position]
def _Draw(self, dc, Canvas):
w, h = Canvas.Size
XY = self.XY
if self.Position[0] == 'b':
XY = (XY[0], h - XY[1] - self.Height)
elif self.Position[0] == 'c':
XY = (XY[0], XY[1] + (h - self.Height)/2)
if self.Position[1] == 'r':
XY = (w - XY[0] - self.Width, XY[1])
elif self.Position[1] == 'c':
XY = (XY[0] + (w - self.Width)/2, XY[1])
dc.DrawBitmapPoint(self.Bitmap, XY, True)
class GridGroup:
def __init__(self, grids=[]):
self.Grids = grids
def _Draw(self, *args):
for grid in self.Grids:
grid._Draw(*args)
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
Point = (45,40)
Box = Canvas.AddCircle(Point,
Diameter = 10,
FillColor = "Black",
LineColor = "Red",
LineWidth = 6)
bmp = wx.Bitmap('NOAA.png')
grids = GridGroup([PixelBitmap(bmp, (10, 10), Position='tl'),
PixelBitmap(bmp, (10, 10), Position='br'),
PixelBitmap(bmp, (10, 10), Position='tr'),
PixelBitmap(bmp, (10, 10), Position='bl'),
PixelBitmap(bmp, (10, 10), Position='cl'),
PixelBitmap(bmp, (10, 10), Position='cr'),
PixelBitmap(bmp, (10, 10), Position='cc'),
PixelBitmap(bmp, (10, 10), Position='tc'),
PixelBitmap(bmp, (10, 10), Position='bc'),
])
Canvas.GridOver = grids
FloatCanvas.EVT_MOTION(Canvas, self.OnMove )
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
app = wx.App(False) # true to get its own output window.
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

View File

@@ -0,0 +1,81 @@
#!/usr/bin/env python
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
Pts = ((45,40), (20, 15), (10, 40), (30,30))
Points = Canvas.AddPointSet(Pts, Diameter=3, Color="Red")
Points.HitLineWidth = 10
Points.Bind(FloatCanvas.EVT_FC_ENTER_OBJECT, self.OnOverPoints)
Points.Bind(FloatCanvas.EVT_FC_LEAVE_OBJECT, self.OnLeavePoints)
Points.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.OnLeftDown)
self.Show()
Canvas.ZoomToBB()
def OnOverPoints(self, obj):
print "Mouse over point: ", obj.FindClosestPoint(obj.HitCoords)
def OnLeavePoints(self, obj):
print "Mouse left point: ", obj.FindClosestPoint(obj.HitCoords)
def OnLeftDown(self, obj):
print "Mouse left down on point: ", obj.FindClosestPoint(obj.HitCoords)
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

255
samples/floatcanvas/PolyEditor.py Executable file
View File

@@ -0,0 +1,255 @@
#!/usr/bin/env python
"""
PolyEditor: a simple app for editing polygons
Used as a demo for FloatCanvas
"""
import numpy as N
import random
import numpy.random as RandomArray
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
# import a local copy:
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
import wx
ID_ABOUT_MENU = wx.ID_ABOUT
ID_ZOOM_TO_FIT_MENU = wx.NewId()
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self,parent, id,title,position,size):
wx.Frame.__init__(self,parent, id,title,position, size)
## Set up the MenuBar
MenuBar = wx.MenuBar()
FileMenu = wx.Menu()
FileMenu.Append(wx.NewId(), "&Close","Close Application")
wx.EVT_MENU(self, FileMenu.FindItem("Close"), self.OnQuit)
MenuBar.Append(FileMenu, "&File")
view_menu = wx.Menu()
view_menu.Append(wx.NewId(), "Zoom to &Fit","Zoom to fit the window")
wx.EVT_MENU(self, view_menu.FindItem("Zoom to &Fit"), self.ZoomToFit)
MenuBar.Append(view_menu, "&View")
help_menu = wx.Menu()
help_menu.Append(ID_ABOUT_MENU, "&About",
"More information About this program")
wx.EVT_MENU(self, ID_ABOUT_MENU, self.OnAbout)
MenuBar.Append(help_menu, "&Help")
self.SetMenuBar(MenuBar)
self.CreateStatusBar()
# Add the Canvas
self.Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
Debug = 0,
BackgroundColor = "DARK SLATE BLUE"
).Canvas
wx.EVT_CLOSE(self, self.OnCloseWindow)
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
FloatCanvas.EVT_LEFT_UP(self.Canvas, self.OnLeftUp )
FloatCanvas.EVT_LEFT_DOWN(self.Canvas, self.OnLeftClick )
self.ResetSelections()
return None
def ResetSelections(self):
self.SelectedPoly = None
self.SelectedPolyOrig = None
self.SelectedPoints = None
self.PointSelected = False
self.SelectedPointNeighbors = None
def OnAbout(self, event):
dlg = wx.MessageDialog(self, "This is a small program to demonstrate\n"
"the use of the FloatCanvas\n",
"About Me", wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def ZoomToFit(self,event):
self.Canvas.ZoomToBB()
def Clear(self,event = None):
self.Canvas.ClearAll()
self.Canvas.SetProjectionFun(None)
self.Canvas.Draw()
def OnQuit(self,event):
self.Close(True)
def OnCloseWindow(self, event):
self.Destroy()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
And moves a point if there is one selected
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
if self.PointSelected:
PolyPoints = self.SelectedPoly.Points
Index = self.SelectedPoints.Index
dc = wx.ClientDC(self.Canvas)
PixelCoords = event.GetPosition()
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetLogicalFunction(wx.XOR)
if self.SelectedPointNeighbors is None:
self.SelectedPointNeighbors = N.zeros((3,2), N.float_)
#fixme: This feels very inelegant!
if Index == 0:
self.SelectedPointNeighbors[0] = self.SelectedPoly.Points[-1]
self.SelectedPointNeighbors[1:3] = self.SelectedPoly.Points[:2]
elif Index == len(self.SelectedPoly.Points)-1:
self.SelectedPointNeighbors[0:2] = self.SelectedPoly.Points[-2:]
self.SelectedPointNeighbors[2] = self.SelectedPoly.Points[0]
else:
self.SelectedPointNeighbors = self.SelectedPoly.Points[Index-1:Index+2]
self.SelectedPointNeighbors = self.Canvas.WorldToPixel(self.SelectedPointNeighbors)
else:
dc.DrawLines(self.SelectedPointNeighbors)
self.SelectedPointNeighbors[1] = PixelCoords
dc.DrawLines(self.SelectedPointNeighbors)
def OnLeftUp(self, event):
## if a point was selected, it's not anymore
if self.PointSelected:
self.SelectedPoly.Points[self.SelectedPoints.Index] = event.GetCoords()
self.SelectedPoly.SetPoints(self.SelectedPoly.Points, copy = False)
self.SelectedPoints.SetPoints(self.SelectedPoly.Points, copy = False)
self.PointSelected = False
self.SelectedPointNeighbors = None
self.Canvas.Draw()
def OnLeftClick(self,event):
## If a click happens outside the polygon, it's no longer selected
self.DeSelectPoly()
self.Canvas.Draw()
def Setup(self, event = None):
"Seting up with some random polygons"
wx.GetApp().Yield()
self.ResetSelections()
self.Canvas.ClearAll()
Range = (-10,10)
# Create a couple of random Polygons
for i, color in enumerate(("LightBlue", "Green", "Purple","Yellow")):
points = RandomArray.uniform(Range[0],Range[1],(6,2))
Poly = self.Canvas.AddPolygon(points,
LineWidth = 2,
LineColor = "Black",
FillColor = color,
FillStyle = 'Solid')
Poly.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.SelectPoly)
self.Canvas.ZoomToBB()
def SelectPoly(self, Object):
Canvas = self.Canvas
if Object is self.SelectedPolyOrig:
pass
else:
if self.SelectedPoly:
self.DeSelectPoly()
self.SelectedPolyOrig = Object
self.SelectedPoly = Canvas.AddPolygon(Object.Points,
LineWidth = 2,
LineColor = "Red",
FillColor = "Red",
FillStyle = "CrossHatch",
InForeground = True)
# Draw points on the Vertices of the Selected Poly:
self.SelectedPoints = Canvas.AddPointSet(Object.Points,
Diameter = 6,
Color = "Red",
InForeground = True)
self.SelectedPoints.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.SelectPointHit)
Canvas.Draw()
def DeSelectPoly(self):
Canvas = self.Canvas
if self.SelectedPolyOrig is not None:
self.SelectedPolyOrig.SetPoints(self.SelectedPoly.Points, copy = False)
self.Canvas.Draw(Force = True)
Canvas.RemoveObject(self.SelectedPoly)
Canvas.RemoveObject(self.SelectedPoints)
self.ResetSelections()
def SelectPointHit(self, PointSet):
PointSet.Index = PointSet.FindClosestPoint(PointSet.HitCoords)
print "point #%i hit"%PointSet.Index
#Index = PointSet.Index
self.PointSelected = True
class PolyEditor(wx.App):
"""
A simple example of making editable shapes with FloatCanvas
"""
def OnInit(self):
wx.InitAllImageHandlers()
frame = DrawFrame(None,
-1,
"FloatCanvas Demo App",
wx.DefaultPosition,
(700,700),
)
self.SetTopWindow(frame)
frame.Show()
frame.Setup()
return True
PolyEditor(0).MainLoop()# put in True if you want output to go to it's own window.

View File

@@ -0,0 +1,379 @@
#!/usr/bin/env python
"""
This is a demo, showing how to work with a "tree" structure
It demonstrates moving objects around, etc, etc.
"""
import wx
#ver = 'local'
ver = 'installed'
if ver == 'installed': ## import the installed version
from wx.lib.floatcanvas import NavCanvas, Resources
from wx.lib.floatcanvas import FloatCanvas as FC
from wx.lib.floatcanvas.Utilities import BBox
print "using installed version:", wx.lib.floatcanvas.__version__
elif ver == 'local':
## import a local version
import sys
sys.path.append("..")
from floatcanvas import NavCanvas, Resources
from floatcanvas import FloatCanvas as FC
from floatcanvas.Utilities import BBox
import numpy as N
## here we create some new mixins:
## fixme: These really belong in floatcanvas package -- but I kind of want to clean it up some first
class MovingObjectMixin:
"""
Methods required for a Moving object
"""
def GetOutlinePoints(self):
"""
Returns a set of points with which to draw the outline when moving the
object.
Points are a NX2 array of (x,y) points in World coordinates.
"""
BB = self.BoundingBox
OutlinePoints = N.array( ( (BB[0,0], BB[0,1]),
(BB[0,0], BB[1,1]),
(BB[1,0], BB[1,1]),
(BB[1,0], BB[0,1]),
)
)
return OutlinePoints
class ConnectorObjectMixin:
"""
Mixin class for DrawObjects that can be connected with lines
Note that this version only works for Objects that have an "XY" attribute:
that is, one that is derived from XHObjectMixin.
"""
def GetConnectPoint(self):
return self.XY
class MovingBitmap(FC.ScaledBitmap, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
pass
class MovingCircle(FC.Circle, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## Circle MovingObjectMixin and ConnectorObjectMixin
pass
class MovingGroup(FC.Group, MovingObjectMixin, ConnectorObjectMixin):
def GetConnectPoint(self):
return self.BoundingBox.Center
class NodeObject(FC.Group, MovingObjectMixin, ConnectorObjectMixin):
"""
A version of the moving group for nodes -- an ellipse with text on it.
"""
def __init__(self,
Label,
XY,
WH,
BackgroundColor = "Yellow",
TextColor = "Black",
InForeground = False,
IsVisible = True):
XY = N.asarray(XY, N.float).reshape(2,)
WH = N.asarray(WH, N.float).reshape(2,)
Label = FC.ScaledText(Label,
XY,
Size = WH[1] / 2.0,
Color = TextColor,
Position = 'cc',
)
self.Ellipse = FC.Ellipse( (XY - WH/2.0),
WH,
FillColor = BackgroundColor,
LineStyle = None,
)
FC.Group.__init__(self, [self.Ellipse, Label], InForeground, IsVisible)
def GetConnectPoint(self):
return self.BoundingBox.Center
class MovingText(FC.ScaledText, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
pass
class MovingTextBox(FC.ScaledTextBox, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
pass
class ConnectorLine(FC.LineOnlyMixin, FC.DrawObject,):
"""
A Line that connects two objects -- it uses the objects to get its coordinates
The objects must have a GetConnectPoint() method.
"""
##fixme: this should be added to the Main FloatCanvas Objects some day.
def __init__(self,
Object1,
Object2,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 1,
InForeground = False):
FC.DrawObject.__init__(self, InForeground)
self.Object1 = Object1
self.Object2 = Object2
self.LineColor = LineColor
self.LineStyle = LineStyle
self.LineWidth = LineWidth
self.CalcBoundingBox()
self.SetPen(LineColor,LineStyle,LineWidth)
self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
def CalcBoundingBox(self):
self.BoundingBox = BBox.fromPoints((self.Object1.GetConnectPoint(),
self.Object2.GetConnectPoint()) )
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
Points = N.array( (self.Object1.GetConnectPoint(),
self.Object2.GetConnectPoint()) )
Points = WorldToPixel(Points)
dc.SetPen(self.Pen)
dc.DrawLines(Points)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.DrawLines(Points)
class TriangleShape1(FC.Polygon, MovingObjectMixin):
def __init__(self, XY, L):
"""
An equilateral triangle object
XY is the middle of the triangle
L is the length of one side of the Triangle
"""
XY = N.asarray(XY)
XY.shape = (2,)
Points = self.CompPoints(XY, L)
FC.Polygon.__init__(self, Points,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 2,
FillColor = "Red",
FillStyle = "Solid")
## Override the default OutlinePoints
def GetOutlinePoints(self):
return self.Points
def CompPoints(self, XY, L):
c = L/ N.sqrt(3)
Points = N.array(((0, c),
( L/2.0, -c/2.0),
(-L/2.0, -c/2.0)),
N.float_)
Points += XY
return Points
### Tree Utilities
### And some hard coded data...
class TreeNode:
dx = 15
dy = 4
def __init__(self, name, Children = []):
self.Name = name
#self.parent = None -- Is this needed?
self.Children = Children
self.Point = None # The coords of the node.
def __str__(self):
return "TreeNode: %s"%self.Name
__repr__ = __str__
## Build Tree:
leaves = [TreeNode(name) for name in ["Assistant VP 1","Assistant VP 2","Assistant VP 3"] ]
VP1 = TreeNode("VP1", Children = leaves)
VP2 = TreeNode("VP2")
CEO = TreeNode("CEO", [VP1, VP2])
Father = TreeNode("Father", [TreeNode("Daughter"), TreeNode("Son")])
elements = TreeNode("Root", [CEO, Father])
def LayoutTree(root, x, y, level):
NumNodes = len(root.Children)
root.Point = (x,y)
x += root.dx
y += (root.dy * level * (NumNodes-1) / 2.0)
for node in root.Children:
LayoutTree(node, x, y, level-1)
y -= root.dy * level
def TraverseTree(root, func):
func(root)
for child in (root.Children):
TraverseTree(child, func)
class DrawFrame(wx.Frame):
"""
A simple frame used for the Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "White",
).Canvas
self.Canvas = Canvas
Canvas.Bind(FC.EVT_MOTION, self.OnMove )
Canvas.Bind(FC.EVT_LEFT_UP, self.OnLeftUp )
self.elements = elements
LayoutTree(self.elements, 0, 0, 3)
self.AddTree(self.elements)
self.Show(True)
self.Canvas.ZoomToBB()
self.MoveObject = None
self.Moving = False
return None
def AddTree(self, root):
Nodes = []
Connectors = []
EllipseW = 15
EllipseH = 4
def CreateObject(node):
if node.Children:
object = NodeObject(node.Name,
node.Point,
(15, 4),
BackgroundColor = "Yellow",
TextColor = "Black",
)
else:
object = MovingTextBox(node.Name,
node.Point,
2.0,
BackgroundColor = "White",
Color = "Black",
Position = "cl",
PadSize = 1
)
node.DrawObject = object
Nodes.append(object)
def AddConnectors(node):
for child in node.Children:
Connector = ConnectorLine(node.DrawObject, child.DrawObject, LineWidth=3, LineColor="Red")
Connectors.append(Connector)
## create the Objects
TraverseTree(root, CreateObject)
## create the Connectors
TraverseTree(root, AddConnectors)
## Add the conenctos to the Canvas first, so they are undernieth the nodes
self.Canvas.AddObjects(Connectors)
## now add the nodes
self.Canvas.AddObjects(Nodes)
# Now bind the Nodes -- DrawObjects must be Added to a Canvas before they can be bound.
for node in Nodes:
#pass
node.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
def ObjectHit(self, object):
if not self.Moving:
self.Moving = True
self.StartPoint = object.HitCoordsPixel
self.StartObject = self.Canvas.WorldToPixel(object.GetOutlinePoints())
self.MoveObject = None
self.MovingObject = object
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
and moves the object it is clicked on
"""
self.SetStatusText("%.4f, %.4f"%tuple(event.Coords))
if self.Moving:
dxy = event.GetPosition() - self.StartPoint
# Draw the Moving Object:
dc = wx.ClientDC(self.Canvas)
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetLogicalFunction(wx.XOR)
if self.MoveObject is not None:
dc.DrawPolygon(self.MoveObject)
self.MoveObject = self.StartObject + dxy
dc.DrawPolygon(self.MoveObject)
def OnLeftUp(self, event):
if self.Moving:
self.Moving = False
if self.MoveObject is not None:
dxy = event.GetPosition() - self.StartPoint
dxy = self.Canvas.ScalePixelToWorld(dxy)
self.MovingObject.Move(dxy)
self.Canvas.Draw(True)
app = wx.PySimpleApp(0)
DrawFrame(None, -1, "FloatCanvas Tree Demo App", wx.DefaultPosition, (700,700) )
app.MainLoop()

View File

@@ -0,0 +1,100 @@
#!/usr/bin/env python
"""
This demonstrates how to use FloatCanvas with a coordinate system where
X and Y have different scales. In the example, a user had:
X data in the range: 50e-6 to 2000e-6
Y data in the range: 0 to 50000
-chb
"""
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
import numpy as N
def YScaleFun(center):
"""
function that returns a scaling vector to scale y data to same range as x data
"""
# center gets ignored in this case
return N.array((5e7, 1), N.float)
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = YScaleFun,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
Point = N.array((50e-6, 0))
Size = N.array(( (2000e-6 - 5e-6), 50000))
Box = Canvas.AddRectangle(Point,
Size,
FillColor = "blue"
)
Canvas.AddText("%s"%(Point,), Point, Position="cr")
Canvas.AddPoint(Point, Diameter=3, Color = "red")
Point = Point + Size
Canvas.AddText("%s"%(Point,), Point, Position="cl")
Canvas.AddPoint(Point, Diameter=3, Color = "red")
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2g, %.2g"%tuple(event.Coords))
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

View File

@@ -0,0 +1,83 @@
#!/usr/bin/env python
"""
This demo shows how to use a ScaledBitmap2 (which is like a scaled bitmap,
but uses memory more efficiently for large images and high zoom levels.)
"""
## Set a path to an Image file here:
ImageFile = "white_tank.jpg"
import wx
import random
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,
ProjectionFun = None,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
Canvas.MaxScale=20 # sets the maximum zoom level
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
# create the image:
image = wx.Image(ImageFile)
self.width, self.height = image.GetSize()
img = FloatCanvas.ScaledBitmap2( image,
(0,0),
Height=image.GetHeight(),
Position = 'tl',
)
Canvas.AddObject(img)
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%i, %i"%tuple(event.Coords))
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
class MyFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
#Adding the SplitterWindow
splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE|wx.SP_3D, size = (800,400))
# add the left Panel
panel1 = wx.Panel(splitter)
panel1.SetBackgroundColour(wx.RED)
# add the Canvas
panel2 = NavCanvas.NavCanvas(splitter,
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
)
Canvas = panel2.Canvas
# put something on the Canvas
Point = (15,10)
Canvas.AddScaledTextBox("A Two Line\nString",
Point,
2,
Color = "Black",
BackgroundColor = None,
LineColor = "Red",
LineStyle = "Solid",
LineWidth = 1,
Width = None,
PadSize = 5,
Family = wx.ROMAN,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'br',
Alignment = "left",
InForeground = False)
wx.CallAfter(Canvas.ZoomToBB)
# set up the Splitter
sash_Position = 300
splitter.SplitVertically(panel1, panel2, sash_Position)
splitter.SetSashSize(10)
min_Pan_size = 40
splitter.SetMinimumPaneSize(min_Pan_size)
self.Fit()
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, title='splitter test')
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(0)
app.MainLoop()

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env python
"""
A simple example of sub-classing the Navcanvas
-- an alternative to simply putting a NavCanvas on your yoru oen panle or whatever
"""
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
"""
A frame used for the Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
panel = NavPanel(self)
self.Show()
class NavPanel(NavCanvas.NavCanvas):
"""
a subclass of NavCAnvas -- with some specific drawing code
"""
def __init__(self, parent):
NavCanvas.NavCanvas.__init__(self,
parent,
ProjectionFun = None,
BackgroundColor = "DARK SLATE BLUE",
)
self.parent_frame = parent
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
# create the image:
self.Canvas.AddPolygon( ( (2,3),
(5,6),
(7,1), ),
FillColor = "red",
)
wx.CallAfter(self.Canvas.ZoomToBB) # so it will get called after everything is created and sized
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.parent_frame.SetStatusText("%f, %f"%tuple(event.Coords))
pass
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

185
samples/floatcanvas/TestSpline.py Executable file
View File

@@ -0,0 +1,185 @@
#!/usr/bin/env python
"""
This is a very small app using the FloatCanvas
It tests the Spline object, including how you can put points together to
create an object with curves and square corners.
"""
import wx
#### import local version:
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas
#from floatcanvas import FloatCanvas as FC
from wx.lib.floatcanvas import FloatCanvas as FC
from wx.lib.floatcanvas import NavCanvas
class Spline(FC.Line):
def __init__(self, *args, **kwargs):
FC.Line.__init__(self, *args, **kwargs)
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
Points = WorldToPixel(self.Points)
dc.SetPen(self.Pen)
dc.DrawSpline(Points)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.DrawSpline(Points)
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
## Set up the MenuBar
MenuBar = wx.MenuBar()
file_menu = wx.Menu()
item = file_menu.Append(-1, "&Close","Close this frame")
self.Bind(wx.EVT_MENU, self.OnQuit, item)
MenuBar.Append(file_menu, "&File")
help_menu = wx.Menu()
item = help_menu.Append(-1, "&About",
"More information About this program")
self.Bind(wx.EVT_MENU, self.OnAbout, item)
MenuBar.Append(help_menu, "&Help")
self.SetMenuBar(MenuBar)
self.CreateStatusBar()
# Add the Canvas
self.Canvas = NavCanvas.NavCanvas(self,
BackgroundColor = "White",
).Canvas
self.Canvas.Bind(FC.EVT_MOTION, self.OnMove)
wx.EVT_CLOSE(self, self.OnCloseWindow)
self.DrawTest()
self.Show()
self.Canvas.ZoomToBB()
def OnAbout(self, event):
print "OnAbout called"
dlg = wx.MessageDialog(self, "This is a small program to demonstrate\n"
"the use of the FloatCanvas\n",
"About Me", wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
def OnQuit(self,event):
self.Close(True)
def OnCloseWindow(self, event):
self.Destroy()
def DrawTest(self,event=None):
wx.GetApp().Yield()
Canvas = self.Canvas
Points = [(0, 0),
(200,0),
(200,0),
(200,0),
(200,15),
(185,15),
(119,15),
(104,15),
(104,30),
(104,265),
(104,280),
(119,280),
(185,280),
(200,280),
(200,295),
(200,295),
(200,295),
(0, 295),
(0, 295),
(0, 295),
(0, 280),
(15, 280),
(81, 280),
(96, 280),
(96, 265),
(96, 30),
(96, 15),
(81, 15),
(15, 15),
(0, 15),
(0, 0),
]
Canvas.ClearAll()
MyLine = FC.Spline(Points,
LineWidth = 3,
LineColor = "Blue")
Canvas.AddObject(MyLine)
Canvas.AddPointSet(Points,
Color = "Red",
Diameter = 4,
)
## A regular old spline:
Points = [(-30, 260),
(-10, 130),
(70, 185),
(160,60),
]
Canvas.AddSpline(Points,
LineWidth = 5,
LineColor = "Purple")
class DemoApp(wx.App):
def __init__(self, *args, **kwargs):
wx.App.__init__(self, *args, **kwargs)
def OnInit(self):
frame = DrawFrame(None, title="FloatCanvas Spline Demo", size = (700,700))
self.SetTopWindow(frame)
return True
app = DemoApp(False)# put in True if you want output to go to it's own window.
app.MainLoop()

302
samples/floatcanvas/TextBox.py Executable file
View File

@@ -0,0 +1,302 @@
#!/usr/bin/env python
"""
A test and demo of the features of the ScaledTextBox
"""
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import the local version
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
import numpy as N
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self,parent, id,title,position,size):
wx.Frame.__init__(self,parent, id,title,position, size)
# Add the Canvas
self.CreateStatusBar()
Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
Point = (45,40)
Box = Canvas.AddScaledTextBox("A Two Line\nString",
Point,
2,
Color = "Black",
BackgroundColor = None,
LineColor = "Red",
LineStyle = "Solid",
LineWidth = 1,
Width = None,
PadSize = 5,
Family = wx.ROMAN,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'br',
Alignment = "left",
InForeground = False)
# All defaults
Box = Canvas.AddScaledTextBox("A Two Line\nString",
Point,
2)
Box = Canvas.AddScaledTextBox("A Two Line\nString",
Point,
2,
BackgroundColor = "Yellow",
LineColor = "Red",
LineStyle = "Solid",
PadSize = 5,
Family = wx.TELETYPE,
Position = 'bl')
Box = Canvas.AddScaledTextBox("A Two Line\nString",
Point,
2,
BackgroundColor = "Yellow",
LineColor = "Red",
LineStyle = "Solid",
PadSize = 5,
Family = wx.TELETYPE,
Position = 'tr')
Box.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.binding2)
Canvas.AddPoint(Point, Diameter = 4)
Point = (45,15)
Box = Canvas.AddScaledTextBox("A Two Line\nString",
Point,
2,
Color = "Black",
BackgroundColor = 'Red',
LineColor = "Blue",
LineStyle = "LongDash",
LineWidth = 2,
Width = None,
PadSize = 5,
Family = wx.TELETYPE,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'cr',
Alignment = "left",
InForeground = False)
Box = Canvas.AddScaledTextBox("A Two Line\nString",
Point,
1.5,
Color = "Black",
BackgroundColor = 'Red',
LineColor = "Blue",
LineStyle = "LongDash",
LineWidth = 2,
Width = None,
PadSize = 5,
Family = wx.TELETYPE,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'cl',
Alignment = "left",
InForeground = False)
Canvas.AddPoint(Point, Diameter = 4)
Point = (45,-10)
Box = Canvas.AddScaledTextBox("A Two Line\nString",
Point,
2,
Color = "Black",
BackgroundColor = 'Red',
LineColor = "Blue",
LineStyle = "LongDash",
LineWidth = 2,
Width = None,
PadSize = 3,
Family = wx.TELETYPE,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'tc',
Alignment = "left",
InForeground = False)
Box = Canvas.AddScaledTextBox("A three\nLine\nString",
Point,
1.5,
Color = "Black",
BackgroundColor = 'Red',
LineColor = "Blue",
LineStyle = "LongDash",
LineWidth = 2,
Width = None,
PadSize = 0.5,
Family = wx.TELETYPE,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'bc',
Alignment = "left",
InForeground = False)
Canvas.AddPoint(Point, Diameter = 4)
Box = Canvas.AddScaledTextBox("Some Auto Wrapped Text. There is enough to do.",
(80,40),
2,
BackgroundColor = 'White',
LineWidth = 2,
Width = 20,
PadSize = 0.5,
Family = wx.TELETYPE,
)
Box = Canvas.AddScaledTextBox("Some more auto wrapped text. Wrapped to a different width and right aligned.\n\nThis is another paragraph.",
(80,20),
2,
BackgroundColor = 'White',
LineWidth = 2,
Width = 40,
PadSize = 0.5,
Family = wx.ROMAN,
Alignment = "right"
)
Point = N.array((100, -20), N.float_)
Box = Canvas.AddScaledTextBox("Here is even more auto wrapped text. This time the line spacing is set to 0.8. \n\nThe Padding is set to 0.",
Point,
Size = 3,
BackgroundColor = 'White',
LineWidth = 1,
Width = 40,
PadSize = 0.0,
Family = wx.ROMAN,
Position = "cc",
LineSpacing = 0.8
)
Canvas.AddPoint(Point, "Red", 2)
Point = N.array((0, -40), N.float_)
# Point = N.array((0, 0), N.float_)
for Position in ["tl", "bl", "tr", "br"]:
# for Position in ["br"]:
Box = Canvas.AddScaledTextBox("Here is a\nfour liner\nanother line\nPosition=%s"%Position,
Point,
Size = 4,
Color = "Red",
BackgroundColor = None,#'LightBlue',
LineWidth = 1,
LineColor = "White",
Width = None,
PadSize = 2,
Family = wx.ROMAN,
Position = Position,
LineSpacing = 0.8
)
Canvas.AddPoint(Point, "Red", 4)
Point = N.array((-20, 60), N.float_)
Box = Canvas.AddScaledTextBox("Here is some\ncentered\ntext",
Point,
Size = 4,
Color = "Red",
BackgroundColor = 'LightBlue',
LineWidth = 1,
LineColor = "White",
Width = None,
PadSize = 2,
Family = wx.ROMAN,
Position = "tl",
Alignment = "center",
LineSpacing = 0.8
)
Point = N.array((-20, 20), N.float_)
Box = Canvas.AddScaledTextBox("Here is some\nright aligned\ntext",
Point,
Size = 4,
Color = "Red",
BackgroundColor = 'LightBlue',
LineColor = None,
Width = None,
PadSize = 2,
Family = wx.ROMAN,
Position = "tl",
Alignment = "right",
LineSpacing = 0.8
)
Point = N.array((100, -60), N.float_)
Box = Canvas.AddScaledTextBox("Here is some auto wrapped text. This time it is centered, rather than right aligned.\n\nThe Padding is set to 2.",
Point,
Size = 3,
BackgroundColor = 'White',
LineWidth = 1,
Width = 40,
PadSize = 2.0,
Family = wx.ROMAN,
Position = "cc",
LineSpacing = 0.8,
Alignment = 'center',
)
self.Show(True)
self.Canvas.ZoomToBB()
return None
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
def binding(self, event):
print "I'm the Rectangle"
def binding2(self, event):
print "I'm the TextBox"
app = wx.PySimpleApp()
DrawFrame(None, -1, "FloatCanvas Demo App", wx.DefaultPosition, (700,700) )
app.MainLoop()

228
samples/floatcanvas/TextBox2.py Executable file
View File

@@ -0,0 +1,228 @@
#!/usr/bin/env python
"""
A test and demo of the ScaledTextbox.
It also shows how one can use the Mouse to interact and change objects on a Canvas.
this really needs to be re-done with GUI-Modes.
"""
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas, Resources
import numpy as N
LongString = (
"""This is a long string. It is a bunch of text. I am using it to test how the nifty wrapping text box works when you want to re-size.
This is another paragraph. I am trying to make it long enough to wrap a reasonable amount. Let's see how it works.
This is a way to start a paragraph with indenting
"""
)
##LongString = (
##""" This is a not so long string
##Another line""")
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self,parent, id,title,position,size):
wx.Frame.__init__(self,parent, id,title,position, size)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
FloatCanvas.EVT_LEFT_UP(self.Canvas, self.OnLeftUp )
FloatCanvas.EVT_LEFT_DOWN(self.Canvas, self.OnLeftDown)
Point = N.array((0,0), N.float)
Canvas.AddCircle(Point,
Diameter=40,
FillColor="Red",
LineStyle=None,
)
Width = 300
self.Box = Canvas.AddScaledTextBox(LongString,
Point,
10,
Color = "Black",
BackgroundColor = 'White',
LineStyle = "Solid",
LineWidth = 2,
Width = Width,
PadSize = 10.0,
Family = wx.ROMAN,
#Family = wx.TELETYPE,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underlined = False,
Position = 'tl',
LineSpacing = 0.8,
Alignment = "left",
#Alignment = "center",
#Alignment = "right",
InForeground = False)
self.Handle1 = Canvas.AddBitmap(Resources.getMoveCursorBitmap(), Point, Position='cc')
self.Handle2a = Canvas.AddBitmap(Resources.getMoveRLCursorBitmap(), Point, Position='cc')
self.Handle2b = Canvas.AddBitmap(Resources.getMoveRLCursorBitmap(), Point, Position='cc')
self.SetHandles()
self.Handle1.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.Handle1Hit)
self.Handle2a.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.Handle2Hit)
self.Handle2b.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.Handle2Hit)
self.Show(True)
self.Canvas.ZoomToBB()
self.Resizing = False
self.ResizeRect = None
self.Moving = False
return None
def Handle1Hit(self, object):
if not self.Moving:
self.Moving = True
self.StartPoint = object.HitCoordsPixel
def Handle2Hit(self,event=None):
if not self.Resizing:
self.Resizing = True
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
And moves a point if there is one
"""
self.SetStatusText("%.4f, %.4f"%tuple(event.Coords))
if self.Resizing:
((xy),(wh)) = self.Box.GetBoxRect()
(xp, yp) = self.Canvas.WorldToPixel(xy)
(wp, hp) = self.Canvas.ScaleWorldToPixel(wh)
hp = -hp
Corner = event.GetPosition()
if self.Box.Position[1] in 'lc':
wp = max(20, Corner[0]-xp) # don't allow the box to get narrower than 20 pixels
elif self.Box.Position[1] in 'r':
DeltaX = Corner[0]-xp
xp += DeltaX
wp -= DeltaX
# draw the RB box
dc = wx.ClientDC(self.Canvas)
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetLogicalFunction(wx.XOR)
if self.ResizeRect:
dc.DrawRectangle(*self.ResizeRect)
self.ResizeRect = (xp,yp,wp,hp)
dc.DrawRectangle(*self.ResizeRect)
elif self.Moving:
dxy = event.GetPosition() - self.StartPoint
((xy),(wh)) = self.Box.GetBoxRect()
xp, yp = self.Canvas.WorldToPixel(xy) + dxy
(wp, hp) = self.Canvas.ScaleWorldToPixel(wh)
hp = -hp
# draw the RB box
dc = wx.ClientDC(self.Canvas)
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetLogicalFunction(wx.XOR)
if self.ResizeRect:
dc.DrawRectangle(*self.ResizeRect)
self.ResizeRect = (xp,yp,wp,hp)
dc.DrawRectangle(*self.ResizeRect)
def OnLeftDown(self, event):
pass
def OnLeftUp(self, event):
if self.Resizing:
self.Resizing = False
if self.ResizeRect:
Point = self.Canvas.PixelToWorld(self.ResizeRect[:2])
W, H = self.Canvas.ScalePixelToWorld(self.ResizeRect[2:4])
self.ResizeRect = None
self.Box.ReWrap(W)
self.SetHandles()
elif self.Moving:
self.Moving = False
if self.ResizeRect:
dxy = event.GetPosition() - self.StartPoint
dxy = self.Canvas.ScalePixelToWorld(dxy)
self.Box.Move(dxy)
self.ResizeRect = None
# self.Box.SetPoint(Point1)
self.SetHandles()
self.Canvas.Draw(True)
def SetHandles(self):
((x,y),(w,h)) = self.Box.GetBoxRect()
if self.Box.Position[1] in "lc":
x += w
y -= h/3
self.Handle2a.SetPoint((x,y))
y -= h/3
self.Handle2b.SetPoint((x,y))
self.Handle1.SetPoint(self.Box.XY)
app = wx.PySimpleApp()
DrawFrame(None, -1, "FloatCanvas TextBox Test App", wx.DefaultPosition, (700,700) )
app.MainLoop()

View File

@@ -0,0 +1,38 @@
"Another Name","Another Type", 19
-81.531753540039,31.134635925293
-81.531150817871,31.134529113769
-81.530662536621,31.134353637695
-81.530502319336,31.134126663208
-81.530685424805,31.133970260620
-81.531112670898,31.134040832519
-81.532104492188,31.134008407593
-81.532485961914,31.134220123291
-81.533134460449,31.134204864502
-81.534004211426,31.134277343750
-81.534667968750,31.134349822998
-81.534912109375,31.134525299072
-81.534667968750,31.134855270386
-81.534248352051,31.134975433350
-81.533943176270,31.135166168213
-81.533760070801,31.135200500488
-81.532928466797,31.135110855102
-81.532447814941,31.134794235229
-81.532341003418,31.134586334229
"A third 'name'","6", 7
-81.522369384766,31.122062683106
-81.522109985352,31.121908187866
-81.522010803223,31.121685028076
-81.522254943848,31.121658325195
-81.522483825684,31.121797561646
-81.522514343262,31.122062683106
-81.522369384766,31.122062683106
"8223","1", 9
-81.523277282715,31.122261047363
-81.522987365723,31.121982574463
-81.523200988770,31.121547698975
-81.523361206055,31.121408462524
-81.523818969727,31.121549606323
-81.524078369141,31.121662139893
-81.524009704590,31.121944427490
-81.523925781250,31.122068405151
-81.523277282715,31.122261047363

371
samples/floatcanvas/Tree.py Executable file
View File

@@ -0,0 +1,371 @@
#!/usr/bin/env python
"""
This is a demo, showing how to work with a "tree" structure
It demonstrates moving objects around, etc, etc.
"""
import wx
#ver = 'local'
2ver = 'installed'
if ver == 'installed': ## import the installed version
from wx.lib.floatcanvas import NavCanvas, Resources
from wx.lib.floatcanvas import FloatCanvas as FC
from wx.lib.floatcanvas.Utilities import BBox
print "using installed version:", wx.lib.floatcanvas.__version__
elif ver == 'local':
## import a local version
import sys
sys.path.append("..")
from floatcanvas import NavCanvas, Resources
from floatcanvas import FloatCanvas as FC
from floatcanvas.Utilities import BBox
import numpy as N
## here we create some new mixins:
## fixme: These really belong in floatcanvas package -- but I kind of want to clean it up some first
class MovingObjectMixin:
"""
Methods required for a Moving object
"""
def GetOutlinePoints(self):
"""
Returns a set of points with which to draw the outline when moving the
object.
Points are a NX2 array of (x,y) points in World coordinates.
"""
BB = self.BoundingBox
OutlinePoints = N.array( ( (BB[0,0], BB[0,1]),
(BB[0,0], BB[1,1]),
(BB[1,0], BB[1,1]),
(BB[1,0], BB[0,1]),
)
)
return OutlinePoints
class ConnectorObjectMixin:
"""
Mixin class for DrawObjects that can be connected with lines
Note that this version only works for Objects that have an "XY" attribute:
that is, one that is derived from XHObjectMixin.
"""
def GetConnectPoint(self):
return self.XY
class MovingBitmap(FC.ScaledBitmap, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
pass
class MovingCircle(FC.Circle, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## Circle MovingObjectMixin and ConnectorObjectMixin
pass
class MovingGroup(FC.Group, MovingObjectMixin, ConnectorObjectMixin):
def GetConnectPoint(self):
return self.BoundingBox.Center
class NodeObject(FC.Group, MovingObjectMixin, ConnectorObjectMixin):
"""
A version of the moving group for nodes -- an ellipse with text on it.
"""
def __init__(self,
Label,
XY,
WH,
BackgroundColor = "Yellow",
TextColor = "Black",
InForeground = False,
IsVisible = True):
XY = N.asarray(XY, N.float).reshape(2,)
WH = N.asarray(WH, N.float).reshape(2,)
Label = FC.ScaledText(Label,
XY,
Size = WH[1] / 2.0,
Color = TextColor,
Position = 'cc',
)
self.Ellipse = FC.Ellipse( (XY - WH/2.0),
WH,
FillColor = BackgroundColor,
LineStyle = None,
)
FC.Group.__init__(self, [self.Ellipse, Label], InForeground, IsVisible)
def GetConnectPoint(self):
return self.BoundingBox.Center
class MovingText(FC.ScaledText, MovingObjectMixin, ConnectorObjectMixin):
"""
ScaledBitmap Object that can be moved
"""
## All we need to do is is inherit from:
## ScaledBitmap, MovingObjectMixin and ConnectorObjectMixin
pass
class ConnectorLine(FC.LineOnlyMixin, FC.DrawObject,):
"""
A Line that connects two objects -- it uses the objects to get its coordinates
The objects must have a GetConnectPoint() method.
"""
##fixme: this should be added to the Main FloatCanvas Objects some day.
def __init__(self,
Object1,
Object2,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 1,
InForeground = False):
FC.DrawObject.__init__(self, InForeground)
self.Object1 = Object1
self.Object2 = Object2
self.LineColor = LineColor
self.LineStyle = LineStyle
self.LineWidth = LineWidth
self.CalcBoundingBox()
self.SetPen(LineColor,LineStyle,LineWidth)
self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
def CalcBoundingBox(self):
self.BoundingBox = BBox.fromPoints((self.Object1.GetConnectPoint(),
self.Object2.GetConnectPoint()) )
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
Points = N.array( (self.Object1.GetConnectPoint(),
self.Object2.GetConnectPoint()) )
Points = WorldToPixel(Points)
dc.SetPen(self.Pen)
dc.DrawLines(Points)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.DrawLines(Points)
class TriangleShape1(FC.Polygon, MovingObjectMixin):
def __init__(self, XY, L):
"""
An equilateral triangle object
XY is the middle of the triangle
L is the length of one side of the Triangle
"""
XY = N.asarray(XY)
XY.shape = (2,)
Points = self.CompPoints(XY, L)
FC.Polygon.__init__(self, Points,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 2,
FillColor = "Red",
FillStyle = "Solid")
## Override the default OutlinePoints
def GetOutlinePoints(self):
return self.Points
def CompPoints(self, XY, L):
c = L/ N.sqrt(3)
Points = N.array(((0, c),
( L/2.0, -c/2.0),
(-L/2.0, -c/2.0)),
N.float_)
Points += XY
return Points
### Tree Utilities
### And some hard coded data...
class TreeNode:
dx = 15
dy = 4
def __init__(self, name, Children = []):
self.Name = name
#self.parent = None -- Is this needed?
self.Children = Children
self.Point = None # The coords of the node.
def __str__(self):
return "TreeNode: %s"%self.Name
__repr__ = __str__
## Build Tree:
leaves = [TreeNode(name) for name in ["Assistant VP 1","Assistant VP 2","Assistant VP 3"] ]
VP1 = TreeNode("VP1", Children = leaves)
VP2 = TreeNode("VP2")
CEO = TreeNode("CEO", [VP1, VP2])
Father = TreeNode("Father", [TreeNode("Daughter"), TreeNode("Son")])
elements = TreeNode("Root", [CEO, Father])
def LayoutTree(root, x, y, level):
NumNodes = len(root.Children)
root.Point = (x,y)
x += root.dx
y += (root.dy * level * (NumNodes-1) / 2.0)
for node in root.Children:
LayoutTree(node, x, y, level-1)
y -= root.dy * level
def TraverseTree(root, func):
func(root)
for child in (root.Children):
TraverseTree(child, func)
class DrawFrame(wx.Frame):
"""
A simple frame used for the Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,(500,500),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "White",
).Canvas
self.Canvas = Canvas
Canvas.Bind(FC.EVT_MOTION, self.OnMove )
Canvas.Bind(FC.EVT_LEFT_UP, self.OnLeftUp )
self.elements = elements
LayoutTree(self.elements, 0, 0, 3)
self.AddTree(self.elements)
self.Show(True)
self.Canvas.ZoomToBB()
self.MoveObject = None
self.Moving = False
return None
def AddTree(self, root):
Nodes = []
Connectors = []
EllipseW = 15
EllipseH = 4
def CreateObject(node):
if node.Children:
object = NodeObject(node.Name,
node.Point,
(15, 4),
BackgroundColor = "Yellow",
TextColor = "Black",
)
else:
object = MovingText(node.Name,
node.Point,
2.0,
BackgroundColor = "Yellow",
Color = "Red",
Position = "cl",
)
node.DrawObject = object
Nodes.append(object)
def AddConnectors(node):
for child in node.Children:
Connector = ConnectorLine(node.DrawObject, child.DrawObject, LineWidth=3, LineColor="Red")
Connectors.append(Connector)
## create the Objects
TraverseTree(root, CreateObject)
## create the Connectors
TraverseTree(root, AddConnectors)
## Add the conenctos to the Canvas first, so they are undernieth the nodes
self.Canvas.AddObjects(Connectors)
## now add the nodes
self.Canvas.AddObjects(Nodes)
# Now bind the Nodes -- DrawObjects must be Added to a Canvas before they can be bound.
for node in Nodes:
#pass
node.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
def ObjectHit(self, object):
if not self.Moving:
self.Moving = True
self.StartPoint = object.HitCoordsPixel
self.StartObject = self.Canvas.WorldToPixel(object.GetOutlinePoints())
self.MoveObject = None
self.MovingObject = object
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
and moves the object it is clicked on
"""
self.SetStatusText("%.4f, %.4f"%tuple(event.Coords))
if self.Moving:
dxy = event.GetPosition() - self.StartPoint
# Draw the Moving Object:
dc = wx.ClientDC(self.Canvas)
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetLogicalFunction(wx.XOR)
if self.MoveObject is not None:
dc.DrawPolygon(self.MoveObject)
self.MoveObject = self.StartObject + dxy
dc.DrawPolygon(self.MoveObject)
def OnLeftUp(self, event):
if self.Moving:
self.Moving = False
if self.MoveObject is not None:
dxy = event.GetPosition() - self.StartPoint
dxy = self.Canvas.ScalePixelToWorld(dxy)
self.MovingObject.Move(dxy)
self.MoveTri = None
self.Canvas.Draw(True)
app = wx.PySimpleApp(0)
DrawFrame(None, -1, "FloatCanvas Tree Demo App", wx.DefaultPosition, (700,700) )
app.MainLoop()

203
samples/floatcanvas/VectPlot.py Executable file
View File

@@ -0,0 +1,203 @@
#!/usr/bin/env python
"""
A small test app that uses FloatCanvas to draw a vector plot.
"""
import wx
import numpy as N
import random
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas
class DrawFrame(wx.Frame):
def __init__(self,parent, id,title,position,size):
wx.Frame.__init__(self,parent, id,title,position, size)
## Set up the MenuBar
MenuBar = wx.MenuBar()
file_menu = wx.Menu()
item = file_menu.Append(wx.ID_ANY, "E&xit","Terminate the program")
self.Bind(wx.EVT_MENU, self.OnQuit, item)
MenuBar.Append(file_menu, "&File")
draw_menu = wx.Menu()
item = draw_menu.Append(wx.ID_ANY, "&Plot","Re-do Plot")
self.Bind(wx.EVT_MENU, self.Plot, item)
MenuBar.Append(draw_menu, "&Plot")
help_menu = wx.Menu()
item = help_menu.Append(wx.ID_ANY, "&About",
"More information About this program")
self.Bind(wx.EVT_MENU, self.OnAbout, item)
MenuBar.Append(help_menu, "&Help")
self.SetMenuBar(MenuBar)
self.CreateStatusBar()
self.SetStatusText("")
wx.EVT_CLOSE(self, self.OnCloseWindow)
# Add the Canvas
self.Canvas = NavCanvas.NavCanvas(self ,wx.ID_ANY ,(500,300),
ProjectionFun = None,
Debug = 0,
BackgroundColor = "WHITE"
).Canvas
self.Canvas.NumBetweenBlits = 1000
self.Show(True)
self.Plot()
return None
def OnAbout(self, event):
dlg = wx.MessageDialog(self, "This is a small program to demonstrate\n"
"the use of the FloatCanvas\n"
"for vector plotting",
"About Me", wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def ZoomToFit(self,event):
self.Canvas.ZoomToBB()
def OnQuit(self,event):
self.Close(True)
def OnCloseWindow(self, event):
self.Destroy()
def DrawAxis(self):
Canvas = self.Canvas
# Draw the Axis
# Note: the AddRectangle Parameters all have sensible
# defaults. I've put them all here explicitly, so you can see
# what the options are.
self.Canvas.AddRectangle((0, -1.1),
(2*N.pi, 2.2),
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 1,
FillColor = None,
FillStyle = "Solid",
InForeground = 0)
for tic in N.arange(7):
self.Canvas.AddText("%1.1f"%tic,
(tic, -1.1),
Position = 'tc')
for tic in N.arange(-1,1.1,0.5):
self.Canvas.AddText("%1.1f"%tic,
(0,tic),
Position = 'cr')
# Add a phantom rectangle to get the bounding box right
# (the bounding box doesn't get unscaled text right)
self.Canvas.AddRectangle((-0.7, -1.5),
(7, 3),
LineColor = None)
#Canvas.ZoomToBB()
#Canvas.Draw()
def Plot(self, event = None):
x = N.arange(0, 2*N.pi, 0.1)
x.shape = (-1,1)
y = N.sin(x)
data = N.concatenate((x, y),1)
Canvas = self.Canvas
self.Canvas.ClearAll()
self.DrawAxis()
for p in data:
Canvas.AddPoint(p,
Diameter = 4,
Color = "Red",
InForeground = 1)
theta = random.uniform(0, 360)
Canvas.AddArrow(p,
Length = 20,
Direction = p[1]*360,
LineColor = "Red",
)
self.Canvas.ZoomToBB()
self.Canvas.Draw()
self.Canvas.SaveAsImage("junk.png")
class DemoApp(wx.App):
"""
How the demo works:
Either under the Draw menu, or on the toolbar, you can push Run and Stop
"Run" start an oscilloscope like display of a moving sine curve
"Stop" stops it.
While the plot os running (or not) you can zoom in and out and move
about the picture. There is a tool bar with three tools that can be
selected.
The magnifying glass with the plus is the zoom in tool. Once selected,
if you click the image, it will zoom in, centered on where you
clicked. If you click and drag the mouse, you will get a rubber band
box, and the image will zoom to fit that box when you release it.
The magnifying glass with the minus is the zoom out tool. Once selected,
if you click the image, it will zoom out, centered on where you
clicked.
The hand is the move tool. Once selected, if you click and drag on
the image, it will move so that the part you clicked on ends up
where you release the mouse. Nothing is changed while you are
dragging, but you can see the outline of the former picture.
I'd like the cursor to change as you change tools, but the stock
wx.Cursors didn't include anything I liked, so I stuck with the
pointer. Please let me know if you have any nice cursor images for me to
use.
Any bugs, comments, feedback, questions, and especially code are welcome:
-Chris Barker
Chris.Barker@noaa.gov
"""
def OnInit(self):
frame = DrawFrame(None, wx.ID_ANY, "Plotting Test",wx.DefaultPosition,wx.Size(700,400))
self.SetTopWindow(frame)
return True
if __name__ == "__main__":
app = DemoApp(0)
app.MainLoop()

View File

@@ -0,0 +1,95 @@
#!/usr/bin/env python
"""
This demonstrates how to use FloatCanvas with a coordinate system where
Y is increased down, instead of up. This is a standard system for
images, for instance.
Note that there are some problems with doing this for bitmaps and text: things that require positioning.
I'm sure it can be fixed, but I don't have a need for it, so I haven't taken the time yet.
-chb
"""
import wx
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
#import sys
#sys.path.append("..")
#from floatcanvas import NavCanvas, FloatCanvas
import numpy as N
def YDownProjection(CenterPoint):
return N.array((1,-1))
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
ProjectionFun = YDownProjection,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
Point = (0,0)
Box = Canvas.AddRectangle(Point,
(80,100),
FillColor = "blue"
)
Canvas.AddText("%s"%(Point,), Point, Position="cr")
Canvas.AddPoint(Point, Diameter=3, Color = "red")
Point = (0,100)
Canvas.AddText("%s"%(Point,), Point, Position="cr")
Canvas.AddPoint(Point, Diameter=3, Color = "red")
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
self.Show()
Canvas.ZoomToBB()
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB