字体、颜色、图像#

本章将详细介绍Tk如何处理字体、颜色和图像。虽然我们之前已经简要涉及这些主题,但在这里我们将进行更深入的探讨。

字体#

Tk的标签小部件允许你通过字体配置选项来更改显示文本所用的字体。后续章节中介绍的画布和小部件也允许你指定字体。其他显示文本的主题小部件可能没有字体配置选项,但可以通过样式来更改它们的字体。

备注

我们会在稍后详细讨论样式。本质上,它们取代了在单个小部件上调整多个配置选项的旧方法。相反,控制外观的字体、颜色和其他设置可以打包在一个样式中。然后,该样式可以应用到多个小部件上。这与在HTML页面内硬编码显示导向的标记相比,使用CSS将显示特定信息分开的方式类似。

与Tk中的许多内容一样,默认字体通常是一个不错的选择。如果你需要做出更改,本节将向你展示最佳方法,即使用命名字体。Tk包含适用于用户界面所有不同组件的命名字体。它们考虑了你运行的具体平台的习惯。当你需要额外的灵活性时,也可以指定自己的字体。

字体命令参考提供了关于指定字体以及其他与字体相关的操作的完整详细信息。

备注

许多较旧的Tk程序硬编码了字体,使用了下面将要看到的“家族 大小 样式”格式、X11字体名称或较旧且更晦涩的X11字体规范字符串。随着平台的演变,这些应用程序看起来越来越过时。更糟糕的是,字体通常是针对每个小部件单独指定的,导致字体决策分散在整个代码中。特别是Tk提供的标准字体的命名字体是一个更好的解决方案。在任何现有应用程序中,审查和更新字体决策是容易且重要的改变。

标准字体#

每个平台都定义了用于标准用户界面元素的特定字体。Tk将这些决策封装为一组命名的字体,这些字体在所有平台上都可用,尽管具体使用的字体会有所不同。这有助于抽象掉平台之间的差异。当然,标准控件使用这些命名字体。预定义的字体包括:

  • TkDefaultFont: 未特别指定项的默认字体。

  • TkTextFont: 用于输入控件、列表框等。

  • TkFixedFont: 一种标准的固定宽度字体。

  • TkMenuFont: 菜单项使用的字体。

  • TkHeadingFont: 列表和表格中列标题的字体。

  • TkCaptionFont: 窗口和对话框标题栏的字体。

  • TkSmallCaptionFont: 工具对话框较小的标题字体。

  • TkIconFont: 图标标题的字体。

  • TkTooltipFont: 提示信息的字体。

特定平台的字体#

Tk为帮助开发者应对特定平台上较少见的情况,提供了额外的命名字体。各平台的具体指南详细说明了这些字体的使用方式和场合。这些字体只在特定的平台上定义,如果你的应用程序需要跨平台运行,你需要考虑这一因素。

在X11上,Tk识别任何有效的X11字体名称(例如,通过xlsfonts命令查看)。然而,这些字体可能因操作系统、已安装的软件以及个别机器的配置而异。不能保证你的X11系统上的某个字体在其他X11系统上也有安装。

在Windows上,Tk为所有可以在“显示”控制面板中设置的字体提供命名字体。它识别以下字体名称:system, ansi, device, systemfixed, ansifixed, 和 oemfixed。

在macOS上,苹果的人机界面指南(HIG)指定了一系列额外的字体。Tk识别以下名称:systemSystemFont, systemSmallSystemFont, systemApplicationFont, systemViewsFont, systemMenuItemFont, systemMenuItemCmdKeyFont, systemPushButtonFont, systemAlertHeaderFont, systemMiniSystemFont, systemDetailEmphasizedSystemFont, systemEmphasizedSystemFont, systemSmallEmphasizedSystemFont, systemLabelFont, systemMenuTitleFont, systemMenuItemMarkFont, systemWindowTitleFont, systemUtilityWindowTitleFont, systemToolbarFont, 和 systemDetailSystemFont。

命名字体#

在Tkinter中,提供了一些操作来帮助您处理命名字体。您可以从获取当前定义的所有命名字体的列表开始。

from tkinter import font
font.names()

您可以找出由抽象命名字体表示的实际系统字体。这包括家族(例如,Times或Helvetica)、大小(如果为正数则为点数,如果为负数则为像素)、重量(正常或粗体)、斜体(罗马或斜体)以及下划线和删除线的布尔属性。您还可以找出字体的度量(字体中字符有多高以及它是否是等宽字体),甚至测量以该字体渲染的文本片段有多宽多少像素。

>>> from tkinter import font
>>> f = font.nametofont('TkTextFont')
>>> f.actual()
{'family': '.AppleSystemUIFont', 'size': 13, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}
>>> f.metrics()
{'ascent': 13, 'descent': 3, 'linespace': 16, 'fixed': 0}
>>> f.measure('The quick brown fox')
124

Tkinter提供了一个Font类来保存有关命名字体的信息。您可以使用nametofont函数从字体名称创建此类的实例。当您在应用程序中使用命名字体时(例如,通过标签的字体配置选项),您可以提供字体名称(作为字符串)或Font实例。

备注

尝试在交互式shell中运行这些代码并出现错误?即使我们没有在屏幕上显示任何东西,在使用各种字体功能之前也需要初始化Tk。

您还可以创建自己的字体,然后可以像使用预定义字体一样使用它们。为此,请为字体选择一个名称,并根据上述内容指定其字体属性。

from tkinter import font
highlightFont = font.Font(family='Helvetica', name='appHighlightFont', size=12, weight='bold')
ttk.Label(root, text='Attention!', font=highlightFont).grid()

如果您不提供名称,Tkinter将生成一个,您可以通过font.name或str(font)检索到它。通常最好提供一个名称。

family属性指定字体家族。Tk确保Courier、Times和Helvetica的名称可用,尽管它们可能映射到适当的等宽、衬线或无衬线字体)。您可以使用系统上安装的其他字体,但关于可移植性的常规警告适用。您可以使用以下命令获取所有可用家族的名称:

font.families()

备注

您可以使用configure方法更改命名字体的属性。您可能会这样做以响应允许用户放大或缩小菜单选项,即增加或减少字体大小。

字体描述#

另一种指定字体的方法是通过属性列表,以字体家族开头,并可选地包括大小和一个或多个样式选项。一些示例是Helvetica、Helvetica 12、Helvetica 12 bold和Helvetica 12 bold italic。这些字体描述可以在您使用命名字体的任何位置使用,例如,字体配置选项。

一般来说,建议从字体描述切换到命名字体,以便在程序中的一个位置隔离字体差异。

颜色#

与字体一样,有多种方式指定颜色。详细信息可在颜色命令参考中找到。

一般来说,Tk小部件默认为大多数情况下合适的颜色。如果您想更改颜色,可以通过特定于小部件的命令或选项进行,例如标签的前景色和背景色配置选项。对于大多数主题化的小部件,通过样式而不是直接更改小部件本身来指定颜色变化。

您可以通过 RGB 指定颜色,就像在HTML或CSS中一样,例如#3FF#FF016A。Tk 还识别诸如 red, black, grey50, light blue 等名称。

备注

Tk识别X11定义的颜色的标准名称。您可以在上述命令参考中找到完整列表。

与字体一样,macOS和Windows都指定了许多系统特定的抽象颜色名称(再次参见参考资料)。这些颜色对应的实际颜色可能取决于系统设置,并且随时间变化,例如暗模式、文本高亮颜色、默认背景等。

如果需要,您可以使用任何小部件上的winfo_rgb方法找到颜色的RGB值(每个介于0到65535之间)。

root.winfo_rgb('red')

小技巧

不用说,建议在使用颜色时保持克制!

图像#

我们已经看到了使用图像的基础知识,例如在标签或按钮中显示它们。我们通常从磁盘上的文件中创建一个图像对象。

imgobj = PhotoImage(file='myimage.gif')
label['image'] = imgobj

Tk 8.5默认支持GIF和PPM/PNM图像。Tk 8.6添加了对PNG的支持。然而,一个名为Img的Tk扩展库增加了对许多其他格式的支持:BMP、XBM、XPM、JPEG、PNG(如果您使用的是8.5)、TIFF等。尽管Img没有直接包含在Tk核心中,但它通常与其他打包分发一起提供(例如,ActiveTcl)。

Tkinter使用一个专为Python设计的图像库,称为PIL(Python Imaging Library),而不是使用Tk的Img扩展。更具体地说,我们将使用PIL的一个更新分支,称为Pillow。由于它不随Python一起捆绑,您通常需要安装它。您应该能够通过例如pip install Pillow来安装。

from PIL import ImageTk, Image
myimg = ImageTk.PhotoImage(Image.open('myimage.png'))

ImageTk.PhotoImage调用提供了Tk的PhotoImage的即插即用替代品,但支持更广泛的图像类型。

Tk的图像实际上非常强大和复杂,提供了各种方式来检查和修改图像。您可以从图像命令参考和图像命令参考中找到更多信息。

备注

我们在这里看到的多色图像类型在Tk中被称为照片图像。Tk还提供了第二种类型,两比特位图图像,这在90年代广泛使用,当时大多数Unix工作站使用比PC更大的显示器,但它们只是黑白的。不用说,如今颜色大多是必需的,因此将图标等更新为全彩色图像是非常推荐的。虽然在一些可能被视为复古风格的设计中,一些平面和材料设计方案已经回归到黑白。变化总是存在的……