tkinter — Tcl/Tk 的 Python 接口 — Python 文档
tkinter — Tcl/Tk 的 Python 接口
源代码: :source:`Lib/tkinter/__init__.py`
tkinter 包(“Tk 接口”)是 Tk GUI 工具包的标准 Python 接口。 Tk 和 tkinter 在大多数 Unix 平台以及 Windows 系统上都可用。 (Tk 本身不是 Python 的一部分;它在 ActiveState 中维护。)
从命令行运行 python -m tkinter
应该会打开一个窗口,演示一个简单的 Tk 界面,让您知道 tkinter 已正确安装在您的系统上,并显示安装了哪个版本的 Tcl/Tk ,因此您可以阅读特定于该版本的 Tcl/Tk 文档。
也可以看看
Tkinter 文档:
- Python Tkinter 资源
- Python Tkinter 主题指南提供了大量有关从 Python 使用 Tk 的信息以及指向其他 Tk 信息源的链接。
- TKDocs
- 广泛的教程以及一些小部件的友好小部件页面。
- Tkinter 8.5 参考:Python 的 GUI
- 在线参考资料。
- 来自 effbot 的 Tkinter 文档
- effbot.org 支持的 tkinter 在线参考。
- 编程 Python
- Mark Lutz 的书,对 Tkinter 有很好的介绍。
- 忙碌的 Python 开发人员的现代 Tkinter
- Mark Roseman 所著的关于使用 Python 和 Tkinter 构建有吸引力的现代图形用户界面的书。
- Python 和 Tkinter 编程
- 约翰·格雷森 (John Grayson) 着书 (ISBN 1-884777-81-3)。
Tcl/Tk 文档:
- Tk 命令
- 大多数命令都可以作为 tkinter 或 tkinter.ttk 类使用。 更改“8.6”以匹配您的 Tcl/Tk 安装版本。
- Tcl/Tk 最近的手册页
- www.tcl.tk 上最近的 Tcl/Tk 手册。
- ActiveState Tcl 主页
- Tk/Tcl 的开发主要发生在 ActiveState。
- Tcl 和 Tk 工具包
- Tcl 的发明者 John Ousterhout 所著。
- Tcl 和 Tk 中的实用编程
- 布伦特韦尔奇的百科全书。
Tkinter 模块
大多数情况下,tkinter 就是你真正需要的,但也有一些额外的模块可用。 Tk 接口位于名为 _tkinter
的二进制模块中。 该模块包含 Tk 的低级接口,不应由应用程序员直接使用。 它通常是一个共享库(或 DLL),但在某些情况下可能与 Python 解释器静态链接。
除了 Tk 接口模块之外,tkinter 还包括许多 Python 模块,其中 tkinter.constants
是最重要的模块之一。 导入 tkinter 会自动导入 tkinter.constants
,所以,通常,使用 Tkinter 只需要一个简单的导入语句:
import tkinter
或者,更常见的是:
from tkinter import *
- class tkinter.Tk(screenName=None, baseName=None, className='Tk', useTk=1)
- Tk 类是在没有参数的情况下实例化的。 这将创建 Tk 的顶级小部件,它通常是应用程序的主窗口。 每个实例都有自己关联的 Tcl 解释器。
- tkinter.Tcl(screenName=None, baseName=None, className='Tk', useTk=0)
- Tcl() 函数是一个工厂函数,它创建的对象与 Tk 类创建的对象非常相似,只是它不初始化 Tk 子系统。 在不想创建无关的顶层窗口或不能创建的环境(例如没有 X 服务器的 Unix/Linux 系统)中驱动 Tcl 解释器时,这通常很有用。 由 Tcl() 对象创建的对象可以通过调用其
loadtk()
方法来创建顶层窗口(并初始化 Tk 子系统)。
其他提供 Tk 支持的模块包括:
tkinter.scrolledtext
- 内置垂直滚动条的文本小部件。
tkinter.colorchooser
- 让用户选择颜色的对话框。
tkinter.commondialog
- 此处列出的其他模块中定义的对话框的基类。
tkinter.filedialog
- 允许用户指定要打开或保存的文件的通用对话框。
tkinter.font
- 帮助处理字体的实用程序。
tkinter.messagebox
- 访问标准 Tk 对话框。
tkinter.simpledialog
- 基本对话框和便利功能。
tkinter.dnd
- tkinter 的拖放支持。 这是实验性的,当它被 Tk DND 取代时应该被弃用。
turtle
- Tk 窗口中的海龟图形。
Tkinter 生命保护器
本节并非设计为关于 Tk 或 Tkinter 的详尽教程。 相反,它旨在作为一个停止间隙,为系统提供一些介绍性的方向。
学分:
- Tk 是由 John Ousterhout 在伯克利写的。
- Tkinter 由 Steen Lumholt 和 Guido van Rossum 编写。
- 这个 Life Preserver 是由弗吉尼亚大学的 Matt Conway 编写的。
- HTML 渲染和一些自由编辑是由 Ken Manheimer 从 FrameMaker 版本生成的。
- Fredrik Lundh 详细阐述并修改了类接口描述,以使它们与 Tk 4.2 保持同步。
- Mike Clarkson 将文档转换为 LaTeX,并编译了参考手册的用户界面章节。
如何使用本节
本节设计为两部分:前半部分(大致)涵盖背景材料,而后半部分可以作为键盘参考。
当试图回答“我如何做 blah”形式的问题时,通常最好找出如何在直接 Tk 中做“blah”,然后将其转换回相应的 tkinter 调用。 Python 程序员通常可以通过查看 Tk 文档来猜测正确的 Python 命令。 这意味着为了使用 Tkinter,您必须对 Tk 有所了解。 本文档无法履行该角色,因此我们所能做的最好的事情就是向您指出现有的最佳文档。 这里有一些提示:
- 作者强烈建议获取 Tk 手册页的副本。 具体来说,
manN
目录中的手册页最有用。man3
手册页描述了 Tk 库的 C 接口,因此对脚本编写者不是特别有用。 - Addison-Wesley 出版了一本名为 Tcl and the Tk Toolkit 的书,由 John Ousterhout (ISBN 0-201-63337-X) 编写,这是对新手来说很好的 Tcl 和 Tk 介绍。 本书并非详尽无遗,许多细节参见手册页。
tkinter/__init__.py
对大多数人来说是最后的手段,但当其他一切都没有意义时,它可能是一个不错的去处。
一个简单的 Hello World 程序
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack()
self.create_widgets()
def create_widgets(self):
self.hi_there = tk.Button(self)
self.hi_there["text"] = "Hello World\n(click me)"
self.hi_there["command"] = self.say_hi
self.hi_there.pack(side="top")
self.quit = tk.Button(self, text="QUIT", fg="red",
command=self.master.destroy)
self.quit.pack(side="bottom")
def say_hi(self):
print("hi there, everyone!")
root = tk.Tk()
app = Application(master=root)
app.mainloop()
对 Tcl/Tk 的(非常)快速浏览
类层次结构看起来很复杂,但在实际操作中,应用程序程序员几乎总是引用层次结构最底层的类。
笔记:
- 提供这些类是为了在一个命名空间下组织某些功能。 它们并不意味着独立实例化。
- Tk 类旨在在应用程序中仅实例化一次。 应用程序程序员不需要显式实例化一个,只要实例化任何其他类,系统就会创建一个。
Widget
类不打算被实例化,它只用于子类化以制作“真正的”小部件(在 C++ 中,这称为“抽象类”)。
为了使用此参考资料,有时您需要知道如何阅读 Tk 的短文以及如何识别 Tk 命令的各个部分。 (参见 将基本 Tk 映射到 Tkinter 部分,了解下面内容的 tkinter 等价物。)
Tk 脚本是 Tcl 程序。 与所有 Tcl 程序一样,Tk 脚本只是由空格分隔的标记列表。 Tk 小部件只是它的 类 、帮助配置它的 选项 以及使其做有用事情的 操作 。
要在 Tk 中制作小部件,命令始终采用以下形式:
classCommand newPathname options
- 类命令
- 表示要制作哪种小部件(按钮、标签、菜单……)
- 新路径名
- 是此小部件的新名称。 Tk 中的所有名称都必须是唯一的。 为了帮助加强这一点,Tk 中的小部件以 路径名 命名,就像文件系统中的文件一样。 顶级小部件 root 称为
.
(句点),子元素由更多句点分隔。 例如,.myApp.controlPanel.okButton
可能是小部件的名称。 - 选项
- 配置小部件的外观以及在某些情况下的行为。 选项以标志和值列表的形式出现。 标志前面有一个“-”,就像 Unix shell 命令标志一样,如果值超过一个单词,则将它们放在引号中。
例如:
button .fred -fg red -text "hi there"
^ ^ \______________________/
| | |
class new options
command widget (-opt val -opt val ...)
创建后,小部件的路径名成为一个新命令。 这个新的 小部件命令 是程序员让新小部件执行某些 操作 的句柄。 在 C 中,您可以将其表示为 someAction(fred, someOptions),在 C++ 中,您可以将其表示为 fred.someAction(someOptions),而在 Tk 中,您可以说:
.fred someAction someOptions
请注意,对象名称 .fred
以点开头。
如您所料,someAction 的合法值将取决于小部件的类:.fred disable
如果 fred 是按钮(fred 变灰)有效,但如果 fred 无效,则无效标签(Tk 不支持禁用标签)。
someOptions 的合法值取决于动作。 某些操作,例如 disable
,不需要参数,而其他操作,例如文本输入框的 delete
命令,需要参数来指定要删除的文本范围。
将基本 Tk 映射到 Tkinter
Tk 中的类命令对应于 Tkinter 中的类构造函数。
button .fred =====> fred = Button()
对象的主人隐含在创建时赋予它的新名称中。 在 Tkinter 中,明确指定了主人。
button .panel.fred =====> fred = Button(panel)
Tk 中的配置选项在带连字符的标签列表中给出,后跟值。 在 Tkinter 中,选项被指定为实例构造函数中的关键字参数,关键字参数用于配置调用或作为实例索引,以字典样式,用于已建立的实例。 有关设置选项,请参阅部分 设置选项 。
button .fred -fg red =====> fred = Button(panel, fg="red")
.fred configure -fg red =====> fred["fg"] = red
OR ==> fred.config(fg="red")
在 Tk 中,要对小部件执行操作,请将小部件名称用作命令,并在其后跟一个动作名称,可能还带有参数(选项)。 在 Tkinter 中,您可以调用类实例上的方法来调用小部件上的操作。 tkinter/__init__.py
中列出了给定小部件可以执行的操作(方法)。
.fred invoke =====> fred.invoke()
要将小部件提供给打包程序(几何管理器),您可以使用可选参数调用 pack。 在 Tkinter 中,Pack 类拥有所有这些功能,并且各种形式的 pack 命令都被实现为方法。 tkinter 中的所有小部件都是 Packer 的子类,因此继承了所有的打包方法。 有关 Form 几何管理器的更多信息,请参阅 tkinter.tix 模块文档。
pack .fred -side left =====> fred.pack(side="left")
方便参考
设置选项
选项控制小部件的颜色和边框宽度等内容。 可以通过三种方式设置选项:
- 在对象创建时,使用关键字参数
fred = Button(self, fg="red", bg="blue")
- 创建对象后,将选项名称视为字典索引
fred["fg"] = "red" fred["bg"] = "blue"
- 使用 config() 方法在创建对象后更新多个属性
fred.config(fg="red", bg="blue")
有关给定选项及其行为的完整说明,请参阅相关小部件的 Tk 手册页。
请注意,手册页列出了每个小部件的“标准选项”和“小部件特定选项”。 前者是许多小部件共有的选项列表,后者是该特定小部件特有的选项。 标准选项记录在 options(3) 手册页中。
本文档中不区分标准选项和特定于小部件的选项。 某些选项不适用于某些类型的小部件。 给定的小部件是否响应特定选项取决于小部件的类别; 按钮有 command
选项,标签没有。
给定小部件支持的选项列在该小部件的手册页中,或者可以在运行时通过调用不带参数的 config()
方法或调用该小部件上的 keys()
方法来查询。 这些调用的返回值是一个字典,其键是字符串形式的选项名称(例如,'relief'
),其值为 5 元组。
一些选项,如 bg
是具有长名称的常用选项的同义词(bg
是“背景”的简写)。 将 config()
方法传递给速记选项的名称将返回一个 2 元组,而不是 5 元组。 传回的 2 元组将包含同义词的名称和“真实”选项(例如 ('bg', 'background')
)。
指数 | 意义 | 例子 |
---|---|---|
0 | 选项名称 | 'relief'
|
1 | 数据库查找的选项名称 | 'relief'
|
2 | 用于数据库查找的选项类 | 'Relief'
|
3 | 默认值 | 'raised'
|
4 | 当前值 | 'groove'
|
例子:
>>> print(fred.config())
{'relief': ('relief', 'relief', 'Relief', 'raised', 'groove')}
当然,打印的字典将包括所有可用选项及其值。 这仅作为示例。
包装工
封隔器是 Tk 的几何管理机制之一。 几何管理器用于指定小部件在其容器内的相对定位 - 它们的相互 master。 相对于较为繁琐的placer(使用较少,此处不赘述),packer采用定性关系规范——above,to the left of 、filling 等 - 并尽一切努力为您确定确切的放置坐标。
任何 master 小部件的大小由内部“从属小部件”的大小决定。 打包器用于控制从属部件在它们被打包到的主部件中出现的位置。 您可以将小部件打包到框架中,并将框架打包到其他框架中,以实现您想要的那种布局。 此外,一旦打包,该安排会动态调整以适应配置的增量更改。
请注意,在使用几何管理器指定几何之前,小部件不会出现。 忽略几何规范是一个常见的早期错误,然后当小部件被创建但什么也没出现时会感到惊讶。 小部件只有在它应用了例如打包程序的 pack()
方法后才会出现。
可以使用关键字-选项/值对调用 pack() 方法,这些对控制小部件在其容器中的显示位置,以及在调整主应用程序窗口大小时的行为方式。 这里有些例子:
fred.pack() # defaults to side = "top"
fred.pack(side="left")
fred.pack(expand=1)
封隔器选项
有关加壳程序及其可以采用的选项的更多信息,请参阅手册页和 John Ousterhout 的书的第 183 页。
- 锚
- 锚型。 表示包装工将每个奴隶放置在其包裹中的位置。
- 扩张
- 布尔值,
0
或1
。 - 充满
- 合法值:
'x'
、'y'
、'both'
、'none'
。 - ipadx 和 ipady
- 距离 - 在从属部件的每一侧指定内部填充。
- padx 和 pady
- 距离 - 在从属部件的每一侧指定外部填充。
- 边
- 合法值为:
'left'
、'right'
、'top'
、'bottom'
。
耦合小部件变量
某些小部件(如文本输入小部件)的当前值设置可以通过使用特殊选项直接连接到应用程序变量。 这些选项是 variable
、textvariable
、onvalue
、offvalue
和 value
。 这种连接是双向的:如果变量因任何原因发生变化,它所连接的小部件将更新以反映新值。
不幸的是,在 tkinter 的当前实现中,不可能通过 variable
或 textvariable
选项将任意 Python 变量移交给小部件。 唯一适用的变量类型是从一个名为 Variable 的类子类化的变量,该类在 tkinter 中定义。
已经定义了许多有用的 Variable 子类:StringVar
、IntVar
、DoubleVar
和 BooleanVar
。 要读取此类变量的当前值,请对其调用 get()
方法,并调用 set()
方法更改其值。 如果您遵循此协议,小部件将始终跟踪变量的值,而无需您进一步干预。
例如:
import tkinter as tk
class App(tk.Frame):
def __init__(self, master):
super().__init__(master)
self.pack()
self.entrythingy = tk.Entry()
self.entrythingy.pack()
# Create the application variable.
self.contents = tk.StringVar()
# Set it to some value.
self.contents.set("this is a variable")
# Tell the entry widget to watch this variable.
self.entrythingy["textvariable"] = self.contents
# Define a callback for when the user hits return.
# It prints the current value of the variable.
self.entrythingy.bind('<Key-Return>',
self.print_contents)
def print_contents(self, event):
print("Hi. The current entry content is:",
self.contents.get())
root = tk.Tk()
myapp = App(root)
myapp.mainloop()
窗口管理器
在 Tk 中,有一个实用命令 wm
,用于与窗口管理器交互。 wm
命令的选项允许您控制标题、位置、图标位图等内容。 在 tkinter 中,这些命令已作为 Wm
类上的方法实现。 顶级小部件是 Wm
类的子类,因此可以直接调用 Wm
方法。
要获得包含给定小部件的顶级窗口,您通常可以仅参考小部件的主窗口。 当然,如果小部件已打包在框架内,则主窗口将不会代表顶级窗口。 要获得包含任意小部件的顶级窗口,您可以调用 _root()
方法。 此方法以下划线开头,表示此函数是实现的一部分,而不是 Tk 功能的接口。
以下是一些典型用法的示例:
import tkinter as tk
class App(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
# create the application
myapp = App()
#
# here are method calls to the window manager class
#
myapp.master.title("My Do-Nothing Application")
myapp.master.maxsize(1000, 400)
# start the program
myapp.mainloop()
Tk 选项数据类型
- 锚
合法值是罗盘的点数:
"n"
、"ne"
、"e"
、"se"
、"s"
、"sw"
、"w"
、"nw"
以及"center"
。- 位图
有八个内置的命名位图:
'error'
、'gray25'
、'gray50'
、'hourglass'
、'info'
、'questhead'
]、'question'
、'warning'
。 要指定 X 位图文件名,请提供文件的完整路径,并以@
开头,如"@/usr/contrib/bitmap/gumby.bit"
。- 布尔值
您可以传递整数 0 或 1 或字符串
"yes"
或"no"
。- 打回来
这是任何不带参数的 Python 函数。 例如:
def print_it(): print("hi there") fred["command"] = print_it
- 颜色
颜色可以是 rgb.txt 文件中 X 颜色的名称,也可以是表示 4 位 RGB 值的字符串:
"#RGB"
,8 位:"#RRGGBB"
,12 位”"#RRRGGGBBB"
或 16 位"#RRRRGGGGBBBB"
范围,其中 R、G、B 表示任何合法的十六进制数字。 有关详细信息,请参阅 Ousterhout 书中的第 160 页。- 光标
可以使用来自
cursorfont.h
的标准 X 光标名称,无需XC_
前缀。 例如,要获得手形光标 (XC_hand2
),请使用字符串"hand2"
。 您还可以指定自己的位图和遮罩文件。 参见 Ousterhout 书中的第 179 页。- 距离
屏幕距离可以以像素或绝对距离指定。 像素以数字形式给出,绝对距离以字符串形式给出,尾随字符表示单位:
c
表示厘米,i
表示英寸,m
表示毫米,p
] 为打印机点数。 例如,3.5 英寸表示为"3.5i"
。- 字体
Tk 使用列表字体名称格式,例如
{courier 10 bold}
。 带有正数的字体大小以磅为单位; 带有负数的尺寸以像素为单位。- 几何学
这是一个格式为
widthxheight
的字符串,其中大多数小部件的宽度和高度以像素为单位(显示文本的小部件以字符为单位)。 例如:fred["geometry"] = "200x100"
。- 证明合法
合法值为字符串:
"left"
、"center"
、"right"
和"fill"
。- 地区
这是一个包含四个以空格分隔的元素的字符串,每个元素都是一个合法的距离(见上文)。 例如:
"2 3 4 5"
和"3i 2i 4.5i 2i"
和"3c 2c 4c 10.43c"
都是合法的区域。- 宽慰
确定小部件的边框样式是什么。 合法值为:
"raised"
、"sunken"
、"flat"
、"groove"
和"ridge"
。- 滚动命令
这几乎总是某些滚动条小部件的
set()
方法,但可以是任何接受单个参数的小部件方法。- 裹:
必须是以下之一:
"none"
、"char"
或"word"
。
绑定和事件
小部件命令中的 bind 方法允许您监视某些事件并在该事件类型发生时触发回调函数。 bind方法的形式为:
def bind(self, sequence, func, add=''):
在哪里:
- 顺序
- 是一个字符串,表示事件的目标类型。 (有关详细信息,请参阅 John Ousterhout 的书的 bind 手册页和第 201 页)。
- 功能
- 是一个 Python 函数,带有一个参数,在事件发生时被调用。 Event 实例将作为参数传递。 (以这种方式部署的函数通常称为 回调 。)
- 添加
- 是可选的,可以是
或
'+'
。 传递空字符串表示此绑定将替换与此事件关联的任何其他绑定。 传递一个'+'
意味着这个函数将被添加到绑定到这个事件类型的函数列表中。
例如:
def turn_red(self, event):
event.widget["activeforeground"] = "red"
self.button.bind("<Enter>", self.turn_red)
请注意如何在 turn_red()
回调中访问事件的小部件字段。 此字段包含捕获 X 事件的小部件。 下表列出了您可以访问的其他事件字段,以及它们在 Tk 中的表示方式,这在参考 Tk 手册页时非常有用。
TK | Tkinter 事件字段 | TK | Tkinter 事件字段 |
---|---|---|---|
%f | 重点 | %一种 | 字符 |
%H | 高度 | %E | 发送事件 |
%k | 关键代码 | %K | 键符 |
%s | 状态 | %N | keysym_num |
%t | 时间 | %T | 类型 |
%w | 宽度 | %W | 小部件 |
%x | x | %X | x_root |
%y | y | %Y | y_root |
索引参数
许多小部件需要传递“索引”参数。 它们用于指向 Text 小部件中的特定位置,或 Entry 小部件中的特定字符,或 Menu 小部件中的特定菜单项。
- 条目小部件索引(索引、视图索引等)
- 条目小部件具有指代正在显示的文本中的字符位置的选项。 您可以使用这些 tkinter 函数来访问文本小部件中的这些特殊点:
- 文本小部件索引
- Text 小部件的索引符号非常丰富,在 Tk 手册页中得到了最好的描述。
- 菜单索引(menu.invoke(), menu.entryconfig() 等)
- 菜单的一些选项和方法操作特定的菜单条目。 任何时候选项或参数需要菜单索引时,您都可以传入:
- 一个整数,它指的是小部件中条目的数字位置,从顶部开始计数,从 0 开始;
- 字符串
"active"
,指的是当前光标所在的菜单位置; - 字符串
"last"
指的是最后一个菜单项; - 前面有
@
的整数,如@6
,其中整数被解释为菜单坐标系中的 y 像素坐标; - 字符串
"none"
,表示根本没有菜单条目,最常与 menu.activate() 一起使用以停用所有条目,最后, - 从菜单顶部到底部扫描的与菜单条目标签匹配的文本字符串。 请注意,此索引类型是在所有其他类型之后考虑的,这意味着匹配标记为
last
、active
或none
的菜单项可能会被解释为上述文字,而不是.
图片
通过tkinter.Image
对应的子类可以创建不同格式的图片:
BitmapImage
用于 XBM 格式的图像。PhotoImage
适用于 PGM、PPM、GIF 和 PNG 格式的图像。 从 Tk 8.6 开始支持后者。
任一类型的图像都是通过 file
或 data
选项创建的(其他选项也可用)。
然后可以在某些小部件支持 image
选项的任何地方使用图像对象(例如 标签、按钮、菜单)。 在这些情况下,Tk 不会保留对图像的引用。 当最后一个 Python 对图像对象的引用被删除时,图像数据也被删除,并且 Tk 将在使用图像的任何地方显示一个空框。
文件处理程序
Tk 允许您注册和取消注册一个回调函数,当文件描述符上的 I/O 可能时,它将从 Tk 主循环调用。 每个文件描述符只能注册一个处理程序。 示例代码:
import tkinter
widget = tkinter.Tk()
mask = tkinter.READABLE | tkinter.WRITABLE
widget.tk.createfilehandler(file, mask, callback)
...
widget.tk.deletefilehandler(file)
此功能在 Windows 上不可用。
由于您不知道有多少字节可供读取,您可能不想使用 BufferedIOBase 或 TextIOBase read() 或 readline () 方法,因为这些方法会坚持读取预定义的字节数。 对于套接字,recv() 或 recvfrom() 方法可以正常工作; 对于其他文件,使用原始读取或 os.read(file.fileno(), maxbytecount)
。
- Widget.tk.createfilehandler(file, mask, func)
注册文件处理程序回调函数 func。 file 参数可以是具有 fileno() 方法的对象(例如文件或套接字对象),也可以是整数文件描述符。 mask 参数是以下三个常量中的任何一个的 ORed 组合。 回调调用如下:
callback(file, mask)
- Widget.tk.deletefilehandler(file)
- 取消注册文件处理程序。
- tkinter.READABLE
tkinter.WRITABLE
tkinter.EXCEPTION
- mask 参数中使用的常量。