📄 floatcanvas.py
字号:
if self._Canvas and (not self.InForeground):
self._Canvas._ForeDrawList.append(self)
self._Canvas._DrawList.remove(self)
self._Canvas._BackgroundDirty = True
self.InForeground = True
def Hide(self):
self.Visible = False
def Show(self):
self.Visible = True
class ColorOnlyMixin:
"""
Mixin class for objects that have just one color, rather than a fill
color and line color
"""
def SetColor(self, Color):
self.SetPen(Color,"Solid",1)
self.SetBrush(Color,"Solid")
SetFillColor = SetColor # Just to provide a consistant interface
class LineOnlyMixin:
"""
Mixin class for objects that have just one color, rather than a fill
color and line color
"""
def SetLineColor(self, LineColor):
self.LineColor = LineColor
self.SetPen(LineColor,self.LineStyle,self.LineWidth)
def SetLineStyle(self, LineStyle):
self.LineStyle = LineStyle
self.SetPen(self.LineColor,LineStyle,self.LineWidth)
def SetLineWidth(self, LineWidth):
self.LineWidth = LineWidth
self.SetPen(self.LineColor,self.LineStyle,LineWidth)
class LineAndFillMixin(LineOnlyMixin):
"""
Mixin class for objects that have both a line and a fill color and
style.
"""
def SetFillColor(self, FillColor):
self.FillColor = FillColor
self.SetBrush(FillColor, self.FillStyle)
def SetFillStyle(self, FillStyle):
self.FillStyle = FillStyle
self.SetBrush(self.FillColor,FillStyle)
class XYObjectMixin:
"""
This is a mixin class that provides some methods suitable for use
with objects that have a single (x,y) coordinate pair.
"""
def Move(self, Delta ):
"""
Move(Delta): moves the object by delta, where delta is a
(dx,dy) pair. Ideally a Numpy array of shape (2,)
"""
Delta = asarray(Delta, Float)
self.XY += Delta
self.BoundingBox = self.BoundingBox + Delta
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def CalcBoundingBox(self):
## This may get overwritten in some subclasses
self.BoundingBox = array( (self.XY, self.XY), Float )
def SetPoint(self, xy):
xy = array( xy, Float)
xy.shape = (2,)
Delta = xy - self.XY
self.XY = xy
self.BoundingBox = self.BoundingBox + Delta
#self.CalcBoundingBox()
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
class PointsObjectMixin:
"""
This is a mixin class that provides some methods suitable for use
with objects that have a set of (x,y) coordinate pairs.
"""
## This is code for the PointsObjectMixin object, it needs to be adapted and tested.
## Is the neccesary at all: you can always do:
## Object.SetPoints( Object.Points + delta, copy = False)
## def Move(self, Delta ):
## """
## Move(Delta): moves the object by delta, where delta is an (dx,
## dy) pair. Ideally a Numpy array of shape (2,)
## """
## Delta = array(Delta, Float)
## self.XY += Delta
## self.BoundingBox = self.BoundingBox + Delta##array((self.XY, (self.XY + self.WH)), Float)
## if self._Canvas:
## self._Canvas.BoundingBoxDirty = True
def CalcBoundingBox(self):
self.BoundingBox = array(((min(self.Points[:,0]),
min(self.Points[:,1]) ),
(max(self.Points[:,0]),
max(self.Points[:,1]) ) ), Float )
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def SetPoints(self, Points, copy = True):
"""
Sets the coordinates of the points of the object to Points (NX2 array).
By default, a copy is made, if copy is set to False, a reference
is used, iff Points is a NumPy array of Floats. This allows you
to change some or all of the points without making any copies.
For example:
Points = Object.Points
Points += (5,10) # shifts the points 5 in the x dir, and 10 in the y dir.
Object.SetPoints(Points, False) # Sets the points to the same array as it was
"""
if copy:
self.Points = array(Points, Float)
self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point
else:
self.Points = asarray(Points, Float)
self.CalcBoundingBox()
class Polygon(DrawObject,PointsObjectMixin,LineAndFillMixin):
"""
The Polygon class takes a list of 2-tuples, or a NX2 NumPy array of
point coordinates. so that Points[N][0] is the x-coordinate of
point N and Points[N][1] is the y-coordinate or Points[N,0] is the
x-coordinate of point N and Points[N,1] is the y-coordinate for
arrays.
The other parameters specify various properties of the Polygon, and
should be self explanatory.
"""
def __init__(self,
Points,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 1,
FillColor = None,
FillStyle = "Solid",
InForeground = False):
DrawObject.__init__(self,InForeground)
self.Points = array(Points,Float) # this DOES need to make a copy
self.CalcBoundingBox()
self.LineColor = LineColor
self.LineStyle = LineStyle
self.LineWidth = LineWidth
self.FillColor = FillColor
self.FillStyle = FillStyle
self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
self.SetPen(LineColor,LineStyle,LineWidth)
self.SetBrush(FillColor,FillStyle)
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel = None, HTdc=None):
Points = WorldToPixel(self.Points)#.tolist()
dc.SetPen(self.Pen)
dc.SetBrush(self.Brush)
dc.DrawPolygon(Points)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.SetBrush(self.HitBrush)
HTdc.DrawPolygon(Points)
##class PolygonSet(DrawObject):
## """
## The PolygonSet class takes a Geometry.Polygon object.
## so that Points[N] = (x1,y1) and Points[N+1] = (x2,y2). N must be an even number!
## it creates a set of line segments, from (x1,y1) to (x2,y2)
## """
## def __init__(self,PolySet,LineColors,LineStyles,LineWidths,FillColors,FillStyles,InForeground = False):
## DrawObject.__init__(self, InForeground)
## ##fixme: there should be some error checking for everything being the right length.
## self.Points = array(Points,Float)
## self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
## self.LineColors = LineColors
## self.LineStyles = LineStyles
## self.LineWidths = LineWidths
## self.FillColors = FillColors
## self.FillStyles = FillStyles
## self.SetPens(LineColors,LineStyles,LineWidths)
## #def _Draw(self,dc,WorldToPixel,ScaleWorldToPixel):
## def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
## Points = WorldToPixel(self.Points)
## Points.shape = (-1,4)
## dc.DrawLineList(Points,self.Pens)
class Line(DrawObject,PointsObjectMixin,LineOnlyMixin):
"""
The Line class takes a list of 2-tuples, or a NX2 NumPy Float array
of point coordinates.
It will draw a straight line if there are two points, and a polyline
if there are more than two.
"""
def __init__(self,Points,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 1,
InForeground = False):
DrawObject.__init__(self, InForeground)
self.Points = array(Points,Float)
self.CalcBoundingBox()
self.LineColor = LineColor
self.LineStyle = LineStyle
self.LineWidth = LineWidth
self.SetPen(LineColor,LineStyle,LineWidth)
self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
Points = WorldToPixel(self.Points)
dc.SetPen(self.Pen)
dc.DrawLines(Points)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.DrawLines(Points)
class Arrow(DrawObject,XYObjectMixin,LineOnlyMixin):
"""
Arrow(XY, # coords of origin of arrow (x,y)
Length, # length of arrow in pixels
theta, # angle of arrow in degrees: zero is straight up
# angle is to the right
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 1,
ArrowHeadSize = 4,
ArrowHeadAngle = 45,
InForeground = False):
It will draw an arrow , starting at the point, (X,Y) pointing in
direction, theta.
"""
def __init__(self,
XY,
Length,
Direction,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 2, # pixels
ArrowHeadSize = 8, # pixels
ArrowHeadAngle = 30, # degrees
InForeground = False):
DrawObject.__init__(self, InForeground)
self.XY = array(XY, Float)
self.XY.shape = (2,) # Make sure it is a 1X2 array, even if there is only one point
self.Length = Length
self.Direction = float(Direction)
self.ArrowHeadSize = ArrowHeadSize
self.ArrowHeadAngle = float(ArrowHeadAngle)
self.CalcArrowPoints()
self.CalcBoundingBox()
self.LineColor = LineColor
self.LineStyle = LineStyle
self.LineWidth = LineWidth
self.SetPen(LineColor,LineStyle,LineWidth)
##fixme: How should the HitTest be drawn?
self.HitLineWidth = max(LineWidth,self.MinHitLineWidth)
def SetDirection(self, Direction):
self.Direction = float(Direction)
self.CalcArrowPoints()
def SetLength(self, Length):
self.Length = Length
self.CalcArrowPoints()
def SetLengthDirection(self, Length, Direction):
self.Direction = float(Direction)
self.Length = Length
self.CalcArrowPoints()
def SetLength(self, Length):
self.Length = Length
self.CalcArrowPoints()
## fixme: cache this?
def CalcArrowPoints(self):
L = self.Length
S = self.ArrowHeadSize
phi = self.ArrowHeadAngle * pi / 360
theta = (self.Direction-90.0) * pi / 180
ArrowPoints = array( ( (0, L, L - S*cos(phi),L, L - S*cos(phi) ),
(0, 0, S*sin(phi), 0, -S*sin(phi) ) ),
Float )
RotationMatrix = array( ( ( cos(theta), -sin(theta) ),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -