⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 floatcanvas.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 5 页
字号:
                                  ( sin(theta), cos(theta) ) ),
                                Float
                                )
        ArrowPoints = matrixmultiply(RotationMatrix, ArrowPoints)
        self.ArrowPoints = transpose(ArrowPoints)

    def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
        dc.SetPen(self.Pen)
        xy = WorldToPixel(self.XY)
        ArrowPoints = xy + self.ArrowPoints
        dc.DrawLines(ArrowPoints)
        if HTdc and self.HitAble:
            HTdc.SetPen(self.HitPen)
            HTdc.DrawLines(ArrowPoints)

##class LineSet(DrawObject, ObjectSetMixin):
##    """
##    The LineSet class takes a list of 2-tuples, or a NX2 NumPy array of point coordinates.
##    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,Points,LineColors,LineStyles,LineWidths,InForeground = False):
##        DrawObject.__init__(self, InForeground)

##        NumLines = len(Points) / 2
##        ##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.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 PointSet(DrawObject,PointsObjectMixin, ColorOnlyMixin):
    """

    The PointSet class takes a list of 2-tuples, or a NX2 NumPy array of
    point coordinates.

    If Points is a sequence of tuples: Points[N][0] is the x-coordinate of
    point N and Points[N][1] is the y-coordinate.

    If Points is a NumPy array: Points[N,0] is the x-coordinate of point
    N and Points[N,1] is the y-coordinate for arrays.

    Each point will be drawn the same color and Diameter. The Diameter
    is in screen pixels, not world coordinates.

    The hit-test code does not distingish between the points, you will
    only know that one of the points got hit, not which one. You can use
    PointSet.FindClosestPoint(WorldPoint) to find out which one

    In the case of points, the HitLineWidth is used as diameter.

    """
    def __init__(self, Points, Color = "Black", Diameter =  1, InForeground = False):
        DrawObject.__init__(self,InForeground)

        self.Points = array(Points,Float)
        self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point
        self.CalcBoundingBox()
        self.Diameter = Diameter

        self.HitLineWidth = self.MinHitLineWidth
        self.SetColor(Color)

    def SetDiameter(self,Diameter):
            self.Diameter = Diameter
            
    def FindClosestPoint(self, XY):
        """
        
        Returns the index of the closest point to the point, XY, given
        in World coordinates. It's essentially random which you get if
        there are more than one that are the same.

        This can be used to figure out which point got hit in a mouse
        binding callback, for instance. It's a lot faster that using a
        lot of separate points.

        """
        d = self.Points - XY
        return argmin(hypot(d[:,0],d[:,1]))
    

    def DrawD2(self, dc, Points):
        # A Little optimization for a diameter2 - point
        dc.DrawPointList(Points)
        dc.DrawPointList(Points + (1,0))
        dc.DrawPointList(Points + (0,1))
        dc.DrawPointList(Points + (1,1))

    def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
        dc.SetPen(self.Pen)
        Points = WorldToPixel(self.Points)
        if self.Diameter <= 1:
            dc.DrawPointList(Points)
        elif self.Diameter <= 2:
            self.DrawD2(dc, Points)
        else:
            dc.SetBrush(self.Brush)
            radius = int(round(self.Diameter/2))
            ##fixme: I really should add a DrawCircleList to wxPython
            if len(Points) > 100:
                xy = Points
                xywh = concatenate((xy-radius, ones(xy.shape) * self.Diameter ), 1 )
                dc.DrawEllipseList(xywh)
            else:
                for xy in Points:
                    dc.DrawCircle(xy[0],xy[1], radius)
        if HTdc and self.HitAble:
            HTdc.SetPen(self.HitPen)
            HTdc.SetBrush(self.HitBrush)
            if self.Diameter <= 1:
                HTdc.DrawPointList(Points)
            elif self.Diameter <= 2:
                self.DrawD2(HTdc, Points)
            else:
                if len(Points) > 100:
                    xy = Points
                    xywh = concatenate((xy-radius, ones(xy.shape) * self.Diameter ), 1 )
                    HTdc.DrawEllipseList(xywh)
                else:
                    for xy in Points:
                        HTdc.DrawCircle(xy[0],xy[1], radius)

class Point(DrawObject,XYObjectMixin,ColorOnlyMixin):
    """
    
    The Point class takes a 2-tuple, or a (2,) NumPy array of point
    coordinates.

    The Diameter is in screen points, not world coordinates, So the
    Bounding box is just the point, and doesn't include the Diameter.

    The HitLineWidth is used as diameter for the
    Hit Test.

    """
    def __init__(self, XY, Color = "Black", Diameter =  1, 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.CalcBoundingBox()
        self.SetColor(Color)
        self.Diameter = Diameter

        self.HitLineWidth = self.MinHitLineWidth

    def SetDiameter(self,Diameter):
            self.Diameter = Diameter


    def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
        dc.SetPen(self.Pen)
        xy = WorldToPixel(self.XY)
        if self.Diameter <= 1:
            dc.DrawPoint(xy[0], xy[1])
        else:
            dc.SetBrush(self.Brush)
            radius = int(round(self.Diameter/2))
            dc.DrawCircle(xy[0],xy[1], radius)
        if HTdc and self.HitAble:
            HTdc.SetPen(self.HitPen)
            if self.Diameter <= 1:
                HTdc.DrawPoint(xy[0], xy[1])
            else:
                HTdc.SetBrush(self.HitBrush)
                HTdc.DrawCircle(xy[0],xy[1], radius)

class SquarePoint(DrawObject,XYObjectMixin,ColorOnlyMixin):
    """
    
    The SquarePoint class takes a 2-tuple, or a (2,) NumPy array of point
    coordinates. It produces a square dot, centered on Point

    The Size is in screen points, not world coordinates, so the
    Bounding box is just the point, and doesn't include the Size.

    The HitLineWidth is used as diameter for the
    Hit Test.

    """
    def __init__(self, Point, Color = "Black", Size =  4, InForeground = False):
        DrawObject.__init__(self, InForeground)
 
        self.XY = array(Point, Float)
        self.XY.shape = (2,) # Make sure it is a 1X2 array, even if there is only one point
        self.CalcBoundingBox()
        self.SetColor(Color)
        self.Size = Size

        self.HitLineWidth = self.MinHitLineWidth

    def SetSize(self,Size):
            self.Size = Size

    def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
        Size = self.Size
        dc.SetPen(self.Pen)
        xc,yc = WorldToPixel(self.XY)
        
        if self.Size <= 1:
            dc.DrawPoint(xc, yc)
        else:
            x = xc - Size/2.0
            y = yc - Size/2.0
            dc.SetBrush(self.Brush)
            dc.DrawRectangle(x, y, Size, Size)
        if HTdc and self.HitAble:
            HTdc.SetPen(self.HitPen)
            if self.Size <= 1:
                HTdc.DrawPoint(xc, xc)
            else:
                HTdc.SetBrush(self.HitBrush)
                HTdc.DrawRectangle(x, y, Size, Size)

class RectEllipse(DrawObject, XYObjectMixin, LineAndFillMixin):
    def __init__(self, XY, WH,
                 LineColor = "Black",
                 LineStyle = "Solid",
                 LineWidth    = 1,
                 FillColor    = None,
                 FillStyle    = "Solid",
                 InForeground = False):
        
        DrawObject.__init__(self,InForeground)

        self.XY = array( XY, Float)
        self.XY.shape = (2,)
        self.WH = array( WH, Float )
        self.WH.shape = (2,)
        self.BoundingBox = array((self.XY, (self.XY + self.WH)), Float)
        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 SetShape(self, XY, WH):
        self.XY = array( XY, Float)
        self.WH = array( WH, Float )
        self.CalcBoundingBox()


    def SetUpDraw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
        dc.SetPen(self.Pen)
        dc.SetBrush(self.Brush)
        if HTdc and self.HitAble:
            HTdc.SetPen(self.HitPen)
            HTdc.SetBrush(self.HitBrush)
        return ( WorldToPixel(self.XY),
                 ScaleWorldToPixel(self.WH) )

    def CalcBoundingBox(self):
        self.BoundingBox = array((self.XY, (self.XY + self.WH) ), Float)
        self._Canvas.BoundingBoxDirty = True


class Rectangle(RectEllipse):

    def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
        ( XY, WH ) = self.SetUpDraw(dc,
                                    WorldToPixel,
                                    ScaleWorldToPixel,
                                    HTdc)
        dc.DrawRectanglePointSize(XY, WH)
        if HTdc and self.HitAble:
            HTdc.DrawRectanglePointSize(XY, WH)

class Ellipse(RectEllipse):

    def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
        ( XY, WH ) = self.SetUpDraw(dc,
                                    WorldToPixel,
                                    ScaleWorldToPixel,
                                    HTdc)
        dc.DrawEllipsePointSize(XY, WH)
        if HTdc and self.HitAble:
            HTdc.DrawEllipsePointSize(XY, WH)

class Circle(Ellipse):

    def __init__(self, XY, Diameter, **kwargs):
        self.Center = array(XY, Float)
        Diameter = float(Diameter)
        RectEllipse.__init__(self ,
                             self.Center - Diameter/2.0,
                             (Diameter, Diameter),
                             **kwargs)

    def SetDiameter(self, Diameter):
        Diameter = float(Diameter)
        XY = self.Center - (Diameter/2.0)
        self.SetShape(XY,
                      (Diameter, Diameter)
                      )
        
class TextObjectMixin(XYObjectMixin):
    """

    A mix in class that holds attributes and methods that are needed by
    the Text objects

    """
    
    ## I'm caching fonts, because on GTK, getting a new font can take a
    ## while. However, it gets cleared after every full draw as hanging
    ## on to a bunch of large fonts takes a massive amount of memory.

    FontList = {}

    LayoutFontSize = 12 # font size used for calculating layout

    def SetFont(self, Size, Family, Style, Weight, Underline, FaceName):
        self.Font = self.FontList.setdefault( (Size,
                                               Family,
                                               Style,
                                               Weight,
                                               Underline,
                                               FaceName),
                                               wx.Font(Size,
                                                       Family,
                                                       Style, 
                                                       Weight,
                                                       Underline,
                                                       FaceName) )
        return self.Font

    def SetColor(self, Color):
        self.Color = Color

    def SetBackgroundColor(self, BackgroundColor):
        self.BackgroundColor = BackgroundColor

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -