Alright. Thanks for those pointers. Here is what I'm up to. I can group
them but ungrouping becomes a little wonky as it wont release all of the
objects. How do I get the to ungroup properly?
I tried unbindall but it seems that it has to go trough all of the
objects and bind them again. I can do this, Im just worried it will chew
up resources.
Also I wanted to do a BBox.Inside for the hit test but I couldnt think
of a short way of doing it.
Thanks for the help so far.
Cheers
Astan
#!/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 MovingGroup(FC.Group, MovingObjectMixin):
def GetConnectPoint(self):
return self.BoundingBox.Center
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 )
Canvas.Bind(FC.EVT_LEFT_DOWN, self.OnLeftDown )
self.objects = [] #this contains objects on the canvas
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)
self.objects.append(Tri)
Canvas.AddObject(Tri)
Tri.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
Circle = MovingCircle( (1, 3), 2, FillColor="Blue")
self.objects.append(Circle)
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')
)
## then add them to the Canvas, so they are on top of the line
for bmp in Bitmaps:
self.objects.append(bmp)
Canvas.AddObject(bmp)
bmp.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
self.Show(True)
self.Canvas.ZoomToBB()
self.MoveObject = None
self.Moving = False
self.Tol = 5
self.Drawing = False
self.RBRect = None
self.StartPointWorld = None
self.G = None
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)
if self.Drawing:
x, y = self.StartPoint
Cornerx, Cornery = event.GetPosition()
w, h = ( Cornerx - x, Cornery - y)
if abs(w) > self.Tol and abs(h) > self.Tol:
# 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.RBRect:
dc.DrawRectangle(*self.RBRect)
self.RBRect = (x, y, w, h )
dc.DrawRectangle(*self.RBRect)
def OnLeftDown(self,event):
self.Drawing = True
self.StartPoint = event.GetPosition()
self.StartPointWorld = event.Coords
def OnLeftUp(self, event):
if self.Drawing:
self.Drawing = False
if self.RBRect:
WH = event.Coords - self.StartPointWorld #do I even need this?
self.selected_objects = []
if self.G:
self.Canvas.RemoveObject(self.G)
self.G = None
for object in self.objects:
objp = object.GetOutlinePoints()[0] #how do i get position of an object? BBox.Inside is cleaner but long. I like Short.
if self.StartPointWorld[0] < objp[0] and self.StartPointWorld[1] > objp[1] and event.Coords[0] > objp[0] and event.Coords[1] < objp[1]:
#insert better hitText above. BBox.Inside is cleaner but long. I like Short.
self.selected_objects.append(object)
if len(self.selected_objects) > 0:
self.G = MovingGroup(self.selected_objects)
self.Canvas.AddObject(self.G)
self.G.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
self.Canvas.Draw(True)
self.RBRect = None
self.StartPointWorld = None
if self.Moving:
self.Moving = False
self.selected_objects = []
if self.G:
self.Canvas.RemoveObject(self.G)
self.G = None
if self.MoveObject is not None:
dxy = event.GetPosition() - self.StartPoint
dxy = self.Canvas.ScalePixelToWorld(dxy)
self.selected_objects = [self.MovingObject]
self.G = MovingGroup(self.selected_objects)
self.Canvas.AddObject(self.G)
self.G.Bind(FC.EVT_FC_LEFT_DOWN, self.ObjectHit)
self.MovingObject.Move(dxy)
self.MoveTri = None
self.Canvas.Draw(True)
app = wx.PySimpleApp(0)
DrawFrame(None, -1, "FloatCanvas Moving Group Object App", wx.DefaultPosition, (700,700) )
app.MainLoop()
_______________________________________________
FloatCanvas mailing list
[email protected]
http://mail.mithis.com/cgi-bin/mailman/listinfo/floatcanvas