Hi,
In an attempt to modify the MovingElements.py to make group moveable
objects (excluding connector lines), I tried to make a similar class but
with the ability to select a bunch of objects and they will be grouped
together.
Using this, I found that I have problems binding the selected objects to
be moved or unbind them and select new ones (dynamic binding or unbinding).
Also I took the selectionbox code from the floatcanvas.GUI but since the
events doubled up on each other, I included it directly. Im not sure how
to handle events that double up on each other and my implementation to
select is rather crude since I dont know how to get a position of an
object in drawcanvas. Also, Chris I think you mentioned that .AddObject
returns the reference to the drawobject being added, it seems that it
only returns the condition if it added the object or not (i.e. true or
false).
I've attached the code of where Im up to.
Cheers
Astan
David Poundall wrote:
Spot on Chris - Thanks, it worked :-)
-----Original Message-----
From: Christopher Barker [mailto:[EMAIL PROTECTED]
Sent: 14 December 2007 19:51
To: [EMAIL PROTECTED]
Subject: Re: [fc] How to move a group of objects
David Poundall wrote:
Tried the following but to no avail...
R = FC.Rectangle((5, 5),(15, 8), FillColor="Red")
C = FC.Circle( (1, 3), 2, FillColor="Blue")
self.GroupA = FC.Group((R,C))
G = MovingGroup(self.GroupA)
MovingGroup is a subclass of Group, but it can't be created from one.
This might work:
G = MovingGroup((R,C))
Canvas.AddObject(G)
G.Bind(FC.EVT_FC_LEFT_DOWN, self.FCObjectHit)
-Chris
#!/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):
pass
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)
A = MovingArc((-5, 0),(-2, 2),(-5, 2), LineColor="Red", LineWidth=2)
self.objects.append(A)
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
self.Tol = 5
self.Drawing = False
self.RBRect = None
self.StartPointWorld = 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?
G = None
for object in self.objects:
objp = object.GetOutlinePoints()[0] #how do i get position of an object?
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
if G:
G.AddObject(objp)
else:
G = MovingGroup(objp)
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
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 Moving Group Object App", wx.DefaultPosition, (700,700) )
app.MainLoop()
_______________________________________________
FloatCanvas mailing list
[email protected]
http://mail.mithis.com/cgi-bin/mailman/listinfo/floatcanvas