📄 floatcanvas.py
字号:
def SetText(self, String):
"""
Re-sets the text displayed by the object
In the case of the ScaledTextBox, it will re-do the layout as appropriate
Note: only tested with the ScaledTextBox
"""
self.String = String
self.LayoutText()
def LayoutText(self):
"""
A dummy method to re-do the layout of the text.
A derived object needs to override this if required.
"""
pass
## store the function that shift the coords for drawing text. The
## "c" parameter is the correction for world coordinates, rather
## than pixel coords as the y axis is reversed
## pad is the extra space around the text
## if world = 1, the vertical shift is done in y-up coordinates
ShiftFunDict = {'tl': lambda x, y, w, h, world=0, pad=0: (x + pad, y + pad - 2*world*pad),
'tc': lambda x, y, w, h, world=0, pad=0: (x - w/2, y + pad - 2*world*pad),
'tr': lambda x, y, w, h, world=0, pad=0: (x - w - pad, y + pad - 2*world*pad),
'cl': lambda x, y, w, h, world=0, pad=0: (x + pad, y - h/2 + world*h),
'cc': lambda x, y, w, h, world=0, pad=0: (x - w/2, y - h/2 + world*h),
'cr': lambda x, y, w, h, world=0, pad=0: (x - w - pad, y - h/2 + world*h),
'bl': lambda x, y, w, h, world=0, pad=0: (x + pad, y - h + 2*world*h - pad + world*2*pad) ,
'bc': lambda x, y, w, h, world=0, pad=0: (x - w/2, y - h + 2*world*h - pad + world*2*pad) ,
'br': lambda x, y, w, h, world=0, pad=0: (x - w - pad, y - h + 2*world*h - pad + world*2*pad)}
class Text(DrawObject, TextObjectMixin):
"""
This class creates a text object, placed at the coordinates,
x,y. the "Position" argument is a two charactor string, indicating
where in relation to the coordinates the string should be oriented.
The first letter is: t, c, or b, for top, center and bottom The
second letter is: l, c, or r, for left, center and right The
position refers to the position relative to the text itself. It
defaults to "tl" (top left).
Size is the size of the font in pixels, or in points for printing
(if it ever gets implimented). Those will be the same, If you assume
72 PPI.
Family:
Font family, a generic way of referring to fonts without
specifying actual facename. One of:
wx.DEFAULT: Chooses a default font.
wx.DECORATIVE: A decorative font.
wx.ROMAN: A formal, serif font.
wx.SCRIPT: A handwriting font.
wx.SWISS: A sans-serif font.
wx.MODERN: A fixed pitch font.
NOTE: these are only as good as the wxWindows defaults, which aren't so good.
Style:
One of wx.NORMAL, wx.SLANT and wx.ITALIC.
Weight:
One of wx.NORMAL, wx.LIGHT and wx.BOLD.
Underline:
The value can be True or False. At present this may have an an
effect on Windows only.
Alternatively, you can set the kw arg: Font, to a wx.Font, and the
above will be ignored.
The size is fixed, and does not scale with the drawing.
The hit-test is done on the entire text extent
"""
def __init__(self,String, xy,
Size = 12,
Color = "Black",
BackgroundColor = None,
Family = wx.MODERN,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underline = False,
Position = 'tl',
InForeground = False,
Font = None):
DrawObject.__init__(self,InForeground)
self.String = String
# Input size in in Pixels, compute points size from PPI info.
# fixme: for printing, we'll have to do something a little different
self.Size = int(round(72.0 * Size / ScreenPPI))
self.Color = Color
self.BackgroundColor = BackgroundColor
if not Font:
FaceName = ''
else:
FaceName = Font.GetFaceName()
Family = Font.GetFamily()
Size = Font.GetPointSize()
Style = Font.GetStyle()
Underlined = Font.GetUnderlined()
Weight = Font.GetWeight()
self.SetFont(Size, Family, Style, Weight, Underline, FaceName)
self.BoundingBox = array((xy, xy),Float)
self.XY = asarray(xy)
self.XY.shape = (2,)
(self.TextWidth, self.TextHeight) = (None, None)
self.ShiftFun = self.ShiftFunDict[Position]
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
XY = WorldToPixel(self.XY)
dc.SetFont(self.Font)
dc.SetTextForeground(self.Color)
if self.BackgroundColor:
dc.SetBackgroundMode(wx.SOLID)
dc.SetTextBackground(self.BackgroundColor)
else:
dc.SetBackgroundMode(wx.TRANSPARENT)
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, XY)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.SetBrush(self.HitBrush)
HTdc.DrawRectanglePointSize(XY, (self.TextWidth, self.TextHeight) )
class ScaledText(DrawObject, TextObjectMixin):
"""
This class creates a text object that is scaled when zoomed. It is
placed at the coordinates, x,y. the "Position" argument is a two
charactor string, indicating where in relation to the coordinates
the string should be oriented.
The first letter is: t, c, or b, for top, center and bottom The
second letter is: l, c, or r, for left, center and right The
position refers to the position relative to the text itself. It
defaults to "tl" (top left).
Size is the size of the font in world coordinates.
Family:
Font family, a generic way of referring to fonts without
specifying actual facename. One of:
wx.DEFAULT: Chooses a default font.
wx.DECORATI: A decorative font.
wx.ROMAN: A formal, serif font.
wx.SCRIPT: A handwriting font.
wx.SWISS: A sans-serif font.
wx.MODERN: A fixed pitch font.
NOTE: these are only as good as the wxWindows defaults, which aren't so good.
Style:
One of wx.NORMAL, wx.SLANT and wx.ITALIC.
Weight:
One of wx.NORMAL, wx.LIGHT and wx.BOLD.
Underline:
The value can be True or False. At present this may have an an
effect on Windows only.
Alternatively, you can set the kw arg: Font, to a wx.Font, and the
above will be ignored. The size of the font you specify will be
ignored, but the rest of its attributes will be preserved.
The size will scale as the drawing is zoomed.
Bugs/Limitations:
As fonts are scaled, the do end up a little different, so you don't
get exactly the same picture as you scale up and doen, but it's
pretty darn close.
On wxGTK1 on my Linux system, at least, using a font of over about
3000 pts. brings the system to a halt. It's the Font Server using
huge amounts of memory. My work around is to max the font size to
3000 points, so it won't scale past there. GTK2 uses smarter font
drawing, so that may not be an issue in future versions, so feel
free to test. Another smarter way to do it would be to set a global
zoom limit at that point.
The hit-test is done on the entire text extent. This could be made
optional, but I haven't gotten around to it.
"""
def __init__(self, String, XY , Size,
Color = "Black",
BackgroundColor = None,
Family = wx.MODERN,
Style = wx.NORMAL,
Weight = wx.NORMAL,
Underline = False,
Position = 'tl',
Font = None,
InForeground = False):
DrawObject.__init__(self,InForeground)
self.String = String
self.XY = array( XY, Float)
self.XY.shape = (2,)
self.Size = Size
self.Color = Color
self.BackgroundColor = BackgroundColor
self.Family = Family
self.Style = Style
self.Weight = Weight
self.Underline = Underline
if not Font:
self.FaceName = ''
else:
self.FaceName = Font.GetFaceName()
self.Family = Font.GetFamily()
self.Style = Font.GetStyle()
self.Underlined = Font.GetUnderlined()
self.Weight = Font.GetWeight()
# Experimental max font size value on wxGTK2: this works OK on
# my system. If it's a lot larger, there is a crash, with the
# message:
#
# The application 'FloatCanvasDemo.py' lost its
# connection to the display :0.0; most likely the X server was
# shut down or you killed/destroyed the application.
#
# Windows and OS-X seem to be better behaved in this regard.
# They may not draw it, but they don't crash either!
self.MaxFontSize = 1000
self.ShiftFun = self.ShiftFunDict[Position]
self.CalcBoundingBox()
def LayoutText(self):
# This will be called when the text is re-set
# nothing much to be done here
self.CalcBoundingBox()
def CalcBoundingBox(self):
## this isn't exact, as fonts don't scale exactly.
dc = wx.MemoryDC()
bitmap = wx.EmptyBitmap(1, 1)
dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work.
DrawingSize = 40 # pts This effectively determines the resolution that the BB is computed to.
ScaleFactor = float(self.Size) / DrawingSize
dc.SetFont(self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underline, self.FaceName) )
(w,h) = dc.GetTextExtent(self.String)
w = w * ScaleFactor
h = h * ScaleFactor
x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1)
self.BoundingBox = array(((x, y-h ),(x + w, y)),Float)
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
(X,Y) = WorldToPixel( (self.XY) )
# compute the font size:
Size = abs( ScaleWorldToPixel( (self.Size, self.Size) )[1] ) # only need a y coordinate length
## Check to see if the font size is large enough to blow up the X font server
## If so, limit it. Would it be better just to not draw it?
## note that this limit is dependent on how much memory you have, etc.
Size = min(Size, self.MaxFontSize)
dc.SetFont(self.SetFont(Size, self.Family, self.Style, self.Weight, self.Underline, self.FaceName))
dc.SetTextForeground(self.Color)
if self.BackgroundColor:
dc.SetBackgroundMode(wx.SOLID)
dc.SetTextBackground(self.BackgroundColor)
else:
dc.SetBackgroundMode(wx.TRANSPARENT)
(w,h) = dc.GetTextExtent(self.String)
# compute the shift, and adjust the coordinates, if neccesary
# This had to be put in here, because it changes with Zoom, as
# fonts don't scale exactly.
xy = self.ShiftFun(X, Y, w, h)
dc.DrawTextPoint(self.String, xy)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.SetBrush(self.HitBrush)
HTdc.DrawRectanglePointSize(xy, (w, h) )
class ScaledTextBox(DrawObject, TextObjectMixin):
"""
This class creates a TextBox object that is scaled when zoomed. It is
placed at the coordinates, x,y.
If the Width parameter is defined, the text will be wrapped to the width given.
A Box can be drawn around the text, be specifying:
LineWidth and/or FillColor
A space(margin) can be put all the way around the text, be specifying:
the PadSize argument in world coordinates.
The spacing between lines can be adjusted with the:
LineSpacing argument.
The "Position" argument is a two character string, indicating where
in relation to the coordinates the Box should be oriented.
-The first letter is: t, c, or b, for top, center and bottom.
-The second letter is: l, c, or r, for left, center and right The
position refers to the position relative to the text itself. It
defaults to "tl" (top left).
Size is the size of the font in world coordinates.
Family:
Font family, a generic way of referring to fonts without
specifying actual facename. One of:
wx.DEFAULT: Chooses a default font.
wx.DECORATIVE: A decorative font.
wx.ROMAN: A formal, serif font.
wx.SCRIPT: A handwriting font.
wx.SWISS: A sans-serif font.
wx.MODERN: A fixed pitch font.
NOTE: these are only as good as the wxWindows defaults, which aren't so good.
Style:
One of wx.NORMAL, wx.SLANT and wx.ITALIC.
Weight:
One of wx.NORMAL, wx.LIGHT and wx.BOLD.
Underline:
The value can be True or False. At present this may have an an
effect on Windows only.
Alternatively, you can set the kw arg: Font, to a wx.Font, and the
above will be ignored. The size of the font you specify will be
ignored, but the rest of its attributes will be preserved.
The size will scale as the drawing is zoomed.
Bugs/Limitations:
As fonts are scaled, they do end up a little different, so you don't
get exactly the same picture as you scale up and down, but it's
pretty darn close.
On wxGTK1 on my Linux system, at least, using a font of over about
1000 pts. brings the system to a halt. It's the Font Server using
huge amounts of memory. My work around is to max the font size to
1000 points, so it won't scale past there. GTK2 uses smarter font
drawing, so that may not be an issue in future versions, so feel
free to test. Another smarter way to do it would be to set a global
zoom limit at that point.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -