PyCairo 中的文本
最后修改于 2023 年 7 月 17 日
在 PyCairo 教程的这一部分,我们处理文本。
灵魂伴侣
在第一个示例中,我们在窗口上显示一些歌词。
def on_draw(self, wid, cr): cr.set_source_rgb(0.1, 0.1, 0.1) cr.select_font_face("Purisa", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) cr.set_font_size(13) cr.move_to(20, 30) cr.show_text("Most relationships seem so transitory") cr.move_to(20, 60) cr.show_text("They're all good but not the permanent one") cr.move_to(20, 120) cr.show_text("Who doesn't long for someone to hold") cr.move_to(20, 150) cr.show_text("Who knows how to love without being told") cr.move_to(20, 180) cr.show_text("Somebody tell me why I'm on my own") cr.move_to(20, 210) cr.show_text("If there's a soulmate for everyone")
在此代码中,我们显示了 Natasha Bedingfield 的 Soulmate 歌曲中的部分歌词。
cr.select_font_face("Purisa", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
在这里,我们选择字体。该方法接受三个参数:字体系列、字体倾斜和字体粗细。
cr.set_font_size(13)
在这里,我们指定字体大小。
cr.move_to(20, 30) cr.show_text("Most relationships seem so transitory")
我们通过指定文本的位置并调用 show_text
方法将文本显示在窗口上。

居中文本
接下来,我们展示如何将文本居中显示在窗口上。
def on_draw(self, wid, cr): w, h = self.get_size() cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) cr.set_font_size(60) (x, y, width, height, dx, dy) = cr.text_extents("ZetCode") cr.move_to(w/2 - width/2, h/2) cr.show_text("ZetCode")
代码会将文本居中显示在窗口上。即使我们调整窗口大小,它也会保持居中。
w, h = self.get_size()
要在窗口上居中文本,有必要获取窗口客户区的大小。
cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) cr.set_font_size(60)
我们选择一个字体及其大小进行显示。
(x, y, width, height, dx, dy) = cr.text_extents("ZetCode")
我们获取文本的范围。这些是一些描述文本的数字。在我们的示例中,我们需要文本的宽度。
cr.move_to(w/2 - width/2, h/2) cr.show_text("ZetCode")
我们将文本定位在窗口中间,并使用 show_text
方法显示它。

阴影文本
现在我们在窗口上创建阴影文本。
def on_draw(self, wid, cr): cr.select_font_face("Serif", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) cr.set_font_size(50) cr.set_source_rgb(0, 0, 0) cr.move_to(40, 60) cr.show_text("ZetCode") cr.set_source_rgb(0.5, 0.5, 0.5) cr.move_to(43, 63) cr.show_text("ZetCode")
要创建阴影,我们会绘制两次文本。使用不同的颜色。第二次绘制的文本会稍微向右下移动。
cr.set_source_rgb(0, 0, 0) cr.move_to(40, 60) cr.show_text("ZetCode")
第一次绘制的文本是黑色的。它用作阴影。
cr.set_source_rgb(0.5, 0.5, 0.5) cr.move_to(43, 63) cr.show_text("ZetCode")
第二次绘制的文本是灰色的。它向右和向下移动 3 像素。

渐变填充文本
下一个示例会创建一个很好的效果。我们用一些线性渐变填充文本。
def on_draw(self, wid, cr): cr.set_source_rgb(0.2, 0.2, 0.2) cr.paint() h = 90 cr.select_font_face("Serif", cairo.FONT_SLANT_ITALIC, cairo.FONT_WEIGHT_BOLD) cr.set_font_size(h) lg = cairo.LinearGradient(0, 15, 0, h*0.8) lg.set_extend(cairo.EXTEND_REPEAT) lg.add_color_stop_rgb(0.0, 1, 0.6, 0) lg.add_color_stop_rgb(0.5, 1, 0.3, 0) cr.move_to(15, 80) cr.text_path("ZetCode") cr.set_source(lg) cr.fill()
我们在窗口上绘制一个文本,并用线性渐变填充。颜色是一些橙色。
cr.set_source_rgb(0.2, 0.2, 0.2) cr.paint()
为了使其更具视觉吸引力,我们将背景绘制成深灰色。
lg = cairo.LinearGradient(0, 15, 0, h*0.8) lg.set_extend(cairo.EXTEND_REPEAT) lg.add_color_stop_rgb(0.0, 1, 0.6, 0) lg.add_color_stop_rgb(0.5, 1, 0.3, 0)
线性渐变已创建。
cr.move_to(15, 80) cr.text_path("ZetCode") cr.set_source(lg) cr.fill()
文本显示在窗口上。我们使用渐变作为绘制源。

逐个字母
在这个效果中,我们将文本逐个字母显示。字母会延迟绘制。
#!/usr/bin/python ''' ZetCode PyCairo tutorial This program shows text letter by letter. author: Jan Bodnar website: zetcode.com ''' from gi.repository import Gtk, GLib import cairo class cv(object): SPEED = 800 TEXT_SIZE = 35 COUNT_MAX = 8 class Example(Gtk.Window): def __init__(self): super(Example, self).__init__() self.init_ui() self.init_vars() def init_ui(self): self.darea = Gtk.DrawingArea() self.darea.connect("draw", self.on_draw) self.add(self.darea) GLib.timeout_add(cv.SPEED, self.on_timer) self.set_title("Letter by letter") self.resize(350, 200) self.set_position(Gtk.WindowPosition.CENTER) self.connect("delete-event", Gtk.main_quit) self.show_all() def init_vars(self): self.timer = True self.count = 0 self.text = [ "Z", "e", "t", "C", "o", "d", "e" ] def on_timer(self): if not self.timer: return False self.darea.queue_draw() return True def on_draw(self, wid, cr): cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) cr.set_font_size(cv.TEXT_SIZE) dis = 0 for i in range(self.count): (x, y, width, height, dx, dy) = cr.text_extents(self.text[i]) dis += width + 2 cr.move_to(dis + 30, 50) cr.show_text(self.text[i]) self.count += 1 if self.count == cv.COUNT_MAX: self.timer = False self.count = 0 def main(): app = Example() Gtk.main() if __name__ == "__main__": main()
在我们的示例中,我们在 GTK 窗口上逐个字母显示“ZetCode”字符串,并带有延迟。
self.text = [ "Z", "e", "t", "C", "o", "d", "e" ]
这是一个将在窗口上显示的字母列表。
cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
我们选择一种 Courier 字体,加粗。
for i in range(self.count): (x, y, width, height, dx, dy) = cr.text_extents(self.text[i]) dis += width + 2 cr.move_to(dis + 30, 50) cr.show_text(self.text[i])
在这里,我们逐个字母绘制文本。我们获取每个字母的宽度,并计算 x 轴上的距离。
字形
show_text
方法仅适用于简单的文本渲染。Cairo 开发者称之为玩具方法。更专业的文本渲染使用字形完成。字形是提供字符形式的图形符号。字符提供含义。它可以有多个字形。字符没有内在外观。字形没有内在含义。
请注意,许多常见的文本编程需求都由 Pango 库处理。
def on_draw(self, wid, cr): cr.select_font_face("Serif", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) cr.set_font_size(13) glyphs = [] index = 0 for y in range(20): for x in range(35): glyphs.append((index, x*15 + 20, y*18 + 20)) index += 1 cr.show_glyphs(glyphs)
此代码显示了所选字体的 700 个字形。
glyphs = []
字形列表将存储三个整数值。第一个值是所选字体类型的字形索引。第二个和第三个值是字形的 x、y 位置。
cr.show_glyphs(glyphs)
show_glyphs
方法在窗口上显示字形。

本章介绍了 PyCairo 中的文本。