📄 fancytext.py
字号:
setattr(Renderer, "end_%s" % name, end)
if name == "altsigma":
continue # There is no capital for altsigma
def start(self, attrs, code=chr(Alpha+i)):
self.start_font({"encoding" : _greekEncoding})
self.characterData(code)
self.end_font()
setattr(Renderer, "start_%s" % name.capitalize(), start)
setattr(Renderer, "end_%s" % name.capitalize(), end)
_addGreek()
class SizeRenderer(Renderer):
"""Processes text as if rendering it, but just computes the size."""
def __init__(self, dc=None):
Renderer.__init__(self, dc, 0, 0)
def renderCharacterData(self, data, x, y):
pass
def start_angle(self, attrs):
self.characterData("M")
def start_infinity(self, attrs):
width, height = self.dc.GetTextExtent("M")
width = max(width, 10)
height = max(height, width / 2)
self.updateDims(width, height, 0, 0)
def start_times(self, attrs):
self.characterData("M")
def start_in(self, attrs):
self.characterData("M")
def start_times(self, attrs):
self.characterData("M")
class DCRenderer(Renderer):
"""Renders text to a wxPython device context DC."""
def renderCharacterData(self, data, x, y):
self.dc.SetTextForeground(self.getCurrentColor())
self.dc.DrawText(data, x, y)
def start_angle(self, attrs):
self.dc.SetFont(self.getCurrentFont())
self.dc.SetPen(self.getCurrentPen())
width, height, descent, leading = self.dc.GetFullTextExtent("M")
y = self.y + self.offsets[-1]
self.dc.DrawLine(iround(self.x), iround(y), iround( self.x+width), iround(y))
self.dc.DrawLine(iround(self.x), iround(y), iround(self.x+width), iround(y-width))
self.updateDims(width, height, descent, leading)
def start_infinity(self, attrs):
self.dc.SetFont(self.getCurrentFont())
self.dc.SetPen(self.getCurrentPen())
width, height, descent, leading = self.dc.GetFullTextExtent("M")
width = max(width, 10)
height = max(height, width / 2)
self.dc.SetPen(wx.Pen(self.getCurrentColor(), max(1, width/10)))
self.dc.SetBrush(wx.TRANSPARENT_BRUSH)
y = self.y + self.offsets[-1]
r = iround( 0.95 * width / 4)
xc = (2*self.x + width) / 2
yc = iround(y-1.5*r)
self.dc.DrawCircle(xc - r, yc, r)
self.dc.DrawCircle(xc + r, yc, r)
self.updateDims(width, height, 0, 0)
def start_times(self, attrs):
self.dc.SetFont(self.getCurrentFont())
self.dc.SetPen(self.getCurrentPen())
width, height, descent, leading = self.dc.GetFullTextExtent("M")
y = self.y + self.offsets[-1]
width *= 0.8
width = iround(width+.5)
self.dc.SetPen(wx.Pen(self.getCurrentColor(), 1))
self.dc.DrawLine(iround(self.x), iround(y-width), iround(self.x+width-1), iround(y-1))
self.dc.DrawLine(iround(self.x), iround(y-2), iround(self.x+width-1), iround(y-width-1))
self.updateDims(width, height, 0, 0)
def RenderToRenderer(str, renderer, enclose=True):
try:
if enclose:
str = '<?xml version="1.0"?><FancyText>%s</FancyText>' % str
p = xml.parsers.expat.ParserCreate()
p.returns_unicode = 0
p.StartElementHandler = renderer.startElement
p.EndElementHandler = renderer.endElement
p.CharacterDataHandler = renderer.characterData
p.Parse(str, 1)
except xml.parsers.expat.error, err:
raise ValueError('error parsing text text "%s": %s' % (str, err))
# Public interface
def GetExtent(str, dc=None, enclose=True):
"Return the extent of str"
renderer = SizeRenderer(dc)
RenderToRenderer(str, renderer, enclose)
return iceil(renderer.width), iceil(renderer.height) # XXX round up
def GetFullExtent(str, dc=None, enclose=True):
renderer = SizeRenderer(dc)
RenderToRenderer(str, renderer, enclose)
return iceil(renderer.width), iceil(renderer.height), -iceil(renderer.minY) # XXX round up
def RenderToBitmap(str, background=None, enclose=1):
"Return str rendered on a minumum size bitmap"
dc = wx.MemoryDC()
# Chicken and egg problem, we need a bitmap in the DC in order to
# measure how big the bitmap should be...
dc.SelectObject(wx.EmptyBitmap(1,1))
width, height, dy = GetFullExtent(str, dc, enclose)
bmp = wx.EmptyBitmap(width, height)
dc.SelectObject(bmp)
if background is None:
dc.SetBackground(wx.WHITE_BRUSH)
else:
dc.SetBackground(background)
dc.Clear()
renderer = DCRenderer(dc, y=dy)
dc.BeginDrawing()
RenderToRenderer(str, renderer, enclose)
dc.EndDrawing()
dc.SelectObject(wx.NullBitmap)
if background is None:
img = wx.ImageFromBitmap(bmp)
bg = dc.GetBackground().GetColour()
img.SetMaskColour(bg.Red(), bg.Green(), bg.Blue())
bmp = img.ConvertToBitmap()
return bmp
def RenderToDC(str, dc, x, y, enclose=1):
"Render str onto a wxDC at (x,y)"
width, height, dy = GetFullExtent(str, dc)
renderer = DCRenderer(dc, x, y+dy)
RenderToRenderer(str, renderer, enclose)
class StaticFancyText(wx.StaticBitmap):
def __init__(self, window, id, text, *args, **kargs):
args = list(args)
kargs.setdefault('name', 'staticFancyText')
if 'background' in kargs:
background = kargs.pop('background')
elif args:
background = args.pop(0)
else:
background = wx.Brush(window.GetBackgroundColour(), wx.SOLID)
bmp = RenderToBitmap(text, background)
wx.StaticBitmap.__init__(self, window, id, bmp, *args, **kargs)
# Old names for backward compatibiliry
getExtent = GetExtent
renderToBitmap = RenderToBitmap
renderToDC = RenderToDC
# Test Driver
def test():
testText = \
"""<font weight="bold" size="16">FancyText</font> -- <font style="italic" size="16">methods for rendering XML specified text</font>
<font family="swiss" size="12">
This module exports four main methods::
<font family="fixed" style="slant">
def GetExtent(str, dc=None, enclose=True)
def GetFullExtent(str, dc=None, enclose=True)
def RenderToBitmap(str, background=None, enclose=True)
def RenderToDC(str, dc, x, y, enclose=True)
</font>
In all cases, 'str' is an XML string. Note that start and end tags
are only required if *enclose* is set to False. In this case the
text should be wrapped in FancyText tags.
In addition, the module exports one class::
<font family="fixed" style="slant">
class StaticFancyText(self, window, id, text, background, ...)
</font>
This class works similar to StaticText except it interprets its text
as FancyText.
The text can support<sup>superscripts</sup> and <sub>subscripts</sub>, text
in different <font size="20">sizes</font>, <font color="blue">colors</font>, <font style="italic">styles</font>, <font weight="bold">weights</font> and
<font family="script">families</font>. It also supports a limited set of symbols,
currently <times/>, <infinity/>, <angle/> as well as greek letters in both
upper case (<Alpha/><Beta/>...<Omega/>) and lower case (<alpha/><beta/>...<omega/>).
We can use doctest/guitest to display this string in all its marked up glory.
<font family="fixed">
>>> frame = wx.Frame(wx.NULL, -1, "FancyText demo", wx.DefaultPosition)
>>> sft = StaticFancyText(frame, -1, __doc__, wx.Brush("light grey", wx.SOLID))
>>> frame.SetClientSize(sft.GetSize())
>>> didit = frame.Show()
>>> from guitest import PauseTests; PauseTests()
</font></font>
The End"""
app = wx.PySimpleApp()
box = wx.BoxSizer(wx.VERTICAL)
frame = wx.Frame(None, -1, "FancyText demo", wx.DefaultPosition)
frame.SetBackgroundColour("light grey")
sft = StaticFancyText(frame, -1, testText)
box.Add(sft, 1, wx.EXPAND)
frame.SetSizer(box)
frame.SetAutoLayout(True)
box.Fit(frame)
box.SetSizeHints(frame)
frame.Show()
app.MainLoop()
if __name__ == "__main__":
test()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -