# `tkinter` —— Tcl/Tk 的 Python 接口

源代码: Lib/tkinter/__init__.py

`tkinter` 包 ("Tk 接口") 是针对 Tcl/Tk GUI 工具包的标准 Python 接口。 Tk 和 `tkinter` 在大多数 Unix 平台，包括 macOS，以及 Windows 系统上均可使用。

若在命令行执行 `python -m tkinter`，应会弹出一个简单的 Tk 界面窗口， 表明 `tkinter` 包已安装完成，还会显示当前安装的 Tcl/Tk 版本，以便阅读对应版本的 Tcl/Tk 文档。

也參考

- TkDocs

    关于使用 Tkinter 创建用户界面的详细教程。 讲解了关键概念，并介绍了使用现代 API 的推荐方式。

- Tkinter 8.5 参考手册：一种 Python GUI

    详细讲解可用的类、方法和选项的 Tkinter 8.5 参考文档。

Tcl/Tk 资源:

- Tk 命令

    有关 Tkinter 所使用的每个底层 Tcl/Tk 命令的完整参考文档。

- Tcl/Tk 主页

    额外的文档，以及 Tcl/Tk 核心开发相关链接。

书籍:

- Modern Tkinter for Busy Python Developers

    Mark Roseman 著。 (ISBN 978-1999149567)

- Python and Tkinter Programming

    Alan Moore 著。 (ISBN 978-1788835886)

- 使用 Python 编程

    Mark Lutz 著；对 Tkinter 进行了精彩的讲解。 (ISBN 978-0596158101)

- Tcl and the Tk Toolkit (2nd edition)

    John Ousterhout ，Tcl/Tk 的创造者，与 Ken Jones 合著；未涉及 Tkinter。 (ISBN 978-0321336330)

## Tkinter 模块

对 Tkinter 的支持分布在多个模块中。 大多数应用程序将需要主模块 `tkinter`，以及 `tkinter.ttk` 模块，后者提供了带主题的现代部件集及相应的 API:

    from tkinter import *
    from tkinter import ttk

class `tkinter.``Tk`(screenName=None, baseName=None, className='Tk', useTk=True, sync=False, use=None)

  构造一个最高层级的 Tk 部件，这通常是一个应用程序的主窗口，并为这个部件初始化 Tcl 解释器。 每个实例都有其各自所关联的 Tcl 解释器。

  `Tk` 类通常全部使用默认值来初始化。 不过，目前还可识别下列关键字参数:

  screenName

    当（作为字符串）给出时，设置 `DISPLAY` 环境变量。 （仅限 X11）

  baseName

    预置文件的名称。 在默认情况下，baseName 是来自于程序名称 (`sys.argv[0]`)。

  className

    控件类的名称。 会被用作预置文件同时也作为 Tcl 唤起的名称 (interp 中的 argv0)。

  useTk

    如果为 `True`，则初始化 Tk 子系统。 `tkinter.Tcl()` 函数会将其设为 `False`。

  sync

    如果为 `True`，则同步执行所有 X 服务器命令，以便立即报告错误。 可被用于调试。 （仅限 X11）

  use

    指定嵌入应用程序的窗口 id，而不是将其创建为独立的顶层窗口。 id 必须以与顶层控件的 -use 选项值相同的方式来指定（也就是说，它具有与 `winfo_id()` 的返回值相同的形式）。

    请注意在某些平台上只有当 id 是指向一个启用了 -container 选项的 Tk 框架或顶层窗口时此参数才能正确生效。

  `Tk` 读取并解释预置文件，其名称为 `.className.tcl` 和 `.baseName.tcl`，进入 Tcl 解释器并基于 `.className.py` 在 `.baseName.py` 的内容调用 `exec()`。 预置文件的路径为 `HOME` 环境变量，或者如果它未被设置，则为 `os.curdir`。

  `tk`

    通过实例化 `Tk` 创建的 Tk 应用程序对象。 这提供了对 Tcl 解释器的访问。 每个被附加到相同 `Tk` 实例的控件都具有相同的 `tk` 属性值。

  `master`

    包含此控件的控件对象。 对于 `Tk`，master 将为 `None` 因为它是主窗口。 术语 master 和 parent 是类似的且有时作为参数名称被交替使用；但是，调用 `winfo_parent()` 将返回控件名称字符串而 `master` 将返回控件对象。 parent/child 反映了树型关系而 master/slave 反映了容器结构。

  `children`

    以 `dict` 表示的此控件的直接下级其中的键为子控件名称而值为子实例对象。

`tkinter.``Tcl`(screenName=None, baseName=None, className='Tk', useTk=False)

  `Tcl()` 函数是一个工厂函数，它创建的对象类似于 `Tk` 类创建的，只是不会初始化 Tk 子系统。这在调动 Tcl 解释器时最为有用，这时不想创建多余的顶层窗口，或者无法创建（比如不带 X 服务的 Unix/Linux 系统）。由 `Tcl()` 创建的对象可调用 `loadtk()` 方法创建一个顶层窗口（且会初始化 Tk 子系统）。

提供 Tk 支持的模块包括:

`tkinter`

  主 Tkinter 模块。

`tkinter.colorchooser`

  让用户选择颜色的对话框。

`tkinter.commondialog`

  本文其他模块定义的对话框的基类。

`tkinter.filedialog`

  允许用户指定文件的通用对话框，用于打开或保存文件。

`tkinter.font`

  帮助操作字体的工具。

`tkinter.messagebox`

  访问标准的 Tk 对话框。

`tkinter.scrolledtext`

  内置纵向滚动条的文本组件。

`tkinter.simpledialog`

  基础对话框和一些便捷功能。

`tkinter.ttk`

  在 Tk 8.5 中引入的带主题的控件集，提供了对应于 `tkinter` 模块中许多经典控件的现代替代。

附加模块:

`_tkinter`

  一个包含低层级 Tcl/Tk 接口的二进制模块。 它会被主 `tkinter` 模块自动导入，且永远不应被应用程序员所直接使用。 它通常是一个共享库（或 DLL），但在某些情况下可能被动态链接到 Python 解释器。

`idlelib`

  Python 的集成开发与学习环境（IDLE）。 基于 `tkinter`。

`tkinter.constants`

  当向 Tkinter 调用传入各种形参时可被用来代替字符串的符号常量。 由主 `tkinter` 模块自动导入。

`tkinter.dnd`

  针对 `tkinter` 的（实验性的）拖放支持。 当以 Tk DND 代替时它将会被弃用。

`tkinter.tix`

  （已弃用）一个增加了部分新控件的较老的第三方 Tcl/Tk 包。 对多数人来说可以在 `tkinter.ttk` 中找到更好的替代品。

`turtle`

  Tk 窗口中的海龟绘图库。

## Tkinter 拾遗

本节不应作为 Tk 或 Tkinter 的详尽教程。而只是一个补充，提供一些系统指南。

致谢：

- Tk 是 John Ousterhout 在伯克利大学时写的。

- Tkinter 是由 Steen Lumholt 和 Guido van Rossum 编写的。

- 本拾遗由弗吉尼亚大学的 Matt Conway 撰写。

- HTML 渲染和一些自由编辑功能，是由 Ken Manheimer 根据 FrameMaker 创建的。

- Fredrik Lundh 认真研究并修改了类的接口描述，使其与 Tk 4.2 保持一致。

- Mike Clarkson 将文档转换为 LaTeX 格式，并编写了参考手册的用户界面章节。

### 本节内容的用法

本节分为两部分：前半部分（大致）涵盖了背景材料，后半部分可以作为手头的参考手册。

当试图回答“如何才能怎么怎么”这种问题时，通常最好是弄清楚如何直接在 Tk 中实现，然后转换回相应的 `tkinter` 调用。Python 程序员通常可查看 Tk 文档来猜测正确的 Python 命令。这意味着要用好 Tkinter，必须对 Tk 有一定的了解。本文无法完成这个任务，所以最好的做法就是给出目前最好的文档。下面给出一些小提示：

- 作者强烈建议用户先拿到一份 Tk 手册。具体来说，`manN` 目录下的 man 文档是最有用的。`man3` 的 man 文档描述了 Tk 库的 C 接口，因此对脚本编写人员没有什么特别的帮助。

- Addison-Wesley 出版了一本名为《Tcl 和 Tk 工具包》的书，作者是 John Ousterhout（ISBN 0-201-63337-X），对于新手来说，这是一本很好的 Tcl 和Tk 介绍书籍。该书不算详尽，很多细节还是要看 man 手册。

- 对大多数人而言，`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 部件只是它的 class，options 用于进行配置，actions 让它执行有用的动作。

要在 Tk 中制作一个部件，总是采用如下格式的命令：

    classCommand newPathname options

classCommand

  表示要制作何种部件（按钮、标签、菜单......）。

newPathname

  该组件的新名字。Tk 中的所有名字都必须唯一。为了帮助实现这一点，Tk 中的部件都用 路径 命名，就像文件系统中的文件一样。顶层的部件，即 根，名为 `.``（句点），而子部件则由更多的句点分隔。比如部件名可能会是 ``.myApp.controlPanel.okButton` 。

options

  配置部件的外观，有时也能配置行为。这些选项以标志和值的列表形式出现。标志前带一个“-”，就像 Unix shell 命令的标志一样，如果值超过一个单词，就用引号括起来。

例如：

    button   .fred   -fg red -text "hi there"
       ^       ^     \______________________/
       |       |                |
     class    new            options
    command  widget  (-opt val -opt val ...)

一旦创建成功，部件的路径名就成了一条新的命令。这个新的 部件命令 是程序员让新部件执行某些 action 的句柄。在 C 语言中可表示为someAction(fred, someOptions)，在 C++ 中可表示为fred.someAction(someOptions)，而在 Tk 中写作：

    .fred someAction someOptions

请注意，对象名 `.fred` 是以句点开头的。

如您所料，someAction 的可用值取决于部件的类别。如果 fred 为按钮，则 .fred disable 有效（fred 会变灰），而当 fred 为标签时则无效（Tk 不支持标签的禁用）。

someOptions 的合法值取决于动作。有些动作不需要参数，比如 `disable`，其他动作如文本输入框的 `delete` 命令则需用参数指定要删除的文本范围。

## 将简单的 Tk 映射到 Tkinter

Tk 中的类命令对应于 Tkinter 中的类构造函数：

    button .fred                =====>  fred = Button()

父对象是隐含在创建时给定的新名字中的。在 Tkinter 中，父对象是显式指定的：

    button .panel.fred          =====>  fred = Button(panel)

Tk 中的配置项是以连字符标签列表的形式给出的，后跟着参数值。在 Tkinter 中，选项指定为实例构造函数中的关键字参数，在配置调用时指定为关键字 args，或在已有实例中指定为实例索引，以字典的形式。参见 可选配置项 一节的选项设置部分。

    button .fred -fg red        =====>  fred = Button(panel, fg="red")
    .fred configure -fg red     =====>  fred["fg"] = red
                                OR ==>  fred.config(fg="red")

在 Tk 中, 要在某个部件上执行动作, 要用部件名作为命令, 并后面附上动作名称, 可能还会带有参数（option）。在 Tkinter 中，则调用类实例的方法来执行部件的动作。部件能够执行的动作（方法）列在 `tkinter/__init__.py` 中。

    .fred invoke                =====>  fred.invoke()

若要将部件交给打包器（geometry manager），需带上可选参数去调用 pack。在 Tkinter 中，Pack 类拥有全部这些功能，pack 命令的各种形式都以方法的形式实现。 `tkinter` 中的所有部件都是从 Packer 继承而来的，因此继承了所有打包方法。关于Form geometry manager 的更多信息，请参见 `tkinter.tix` 模块的文档。

    pack .fred -side left       =====>  fred.pack(side="left")

## Tk 和 Tkinter 如何关联

自上而下：

（Python）应用程序位于这里

  Python 应用程序进行了 `tkinter` 调用。

tkinter （Python 包）

  此调用（比如创建一个按钮部件）在 `tkinter` 包中实现，它是用 Python 编写的。该 Python 函数将解析命令和参数，并转换为貌似 Tk 脚本的格式，而不像是 Python 脚本。

_tkinter（C 语言）

  这些命令及参数将被传给 `_tkinter` 扩展模块中的 C 函数——注意下划线。

Tk 部件（C 和 Tcl）

  该 C 函数能调用其他的 C 模块，包括构成 Tk 库的 C 函数。Tk 是用 C 和一些 Tcl 实现的。Tk 部件的 Tcl 部分用于将某些默认行为绑定到部件上，并在导入 Python `tkinter` 包时执行一次。（该阶段对用户而言永不可见）。

Tk（C 语言）

  Tk 部件的 Tk 语言部分实现了最终的映射

Xlib（C 语言）

  Xlib 库在屏幕上绘制图形。

## 快速参考

### 可选配置项

配置参数可以控制组件颜色和边框宽度等。可通过三种方式进行设置：

在对象创建时，使用关键字参数

      fred = Button(self, fg="red", bg="blue")

在对象创建后，将参数名用作字典索引

      fred["fg"] = "red"
      fred["bg"] = "blue"

利用 config() 方法修改对象的多个属性

      fred.config(fg="red", bg="blue")

关于这些参数及其表现的完整解释，请参阅 Tk 手册中有关组件的 man 帮助页。

请注意，man 手册页列出了每个部件的“标准选项”和“组件特有选项”。前者是很多组件通用的选项列表，后者是该组件特有的选项。标准选项在 options(3) man 手册中有文档。

本文没有区分标准选项和部件特有选项。有些选项不适用于某类组件。组件是否对某选项做出响应，取决于组件的类别；按钮组件有一个 `command` 选项，而标签组件就没有。

组件支持的选项在其手册中有列出，也可在运行时调用 `config()` 方法（不带参数）查看，或者通过调用组件的 `keys()` 方法进行查询。这些调用的返回值为字典，字典的键是字符串格式的选项名（比如 `'relief'`），字典的值为五元组。

有些选项，比如 `bg` 是全名通用选项的同义词（`bg` 是 “background”的简写）。向 `config()` 方法传入选项的简称将返回一个二元组，而不是五元组。传回的二元组将包含同义词的全名和“真正的”选项（比如 `('bg', 'background')`）。

索引 | 含意 | 示例
--- | --- | ---
0 | 选项名称 | `'relief'`
1 | 数据库查找的选项名称 | `'relief'`
2 | 数据库查找的选项类 | `'Relief'`
3 | 默认值 | `'raised'`
4 | 当前值 | `'groove'`

示例:

    >>> print(fred.config())
    {'relief': ('relief', 'relief', 'Relief', 'raised', 'groove')}

当然，输出的字典将包含所有可用选项及其值。这里只是举个例子。

### 包装器

包装器是 Tk 的形状管理机制之一。 形状（geometry ）管理器用于指定多个部件在容器（共同的 主 组件）内的相对位置。与更为麻烦的 定位器 相比（不太常用，这里不做介绍），包装器可接受定性的相对关系—— 上面 、左边 、填充 等，并确定精确的位置坐标。

主 部件的大小都由其内部的 “从属部件” 的大小决定。包装器用于控制从属部件在主部件中出现的位置。可以把部件包入框架，再把框架包入其他框架中，搭建出所需的布局。此外，只要完成了包装，组件的布局就会进行动态调整，以适应布局参数的变化。

请注意，只有用形状管理器指定几何形状后，部件才会显示出来。忘记设置形状参数是新手常犯的错误，惊讶于创建完部件却啥都没出现。部件只有在应用了类似于打包器的 `pack()` 方法之后才会显示在屏幕上。

调用 pack() 方法时可以给出由关键字/参数值组成的键值对，以便控制组件在其容器中出现的位置，以及主程序窗口大小变动时的行为。下面是一些例子：

    fred.pack()                     # defaults to side = "top"
    fred.pack(side="left")
    fred.pack(expand=1)

### 包装器的参数

关于包装器及其可接受的参数，更多信息请参阅 man 手册和 John Ousterhout 书中的第 183 页。

anchor

  anchor 类型。 表示包装器要放置的每个从属组件的位置。

expand

  布尔型，`0` 或 `1` 。

fill

  合法值为：`'x'` 、`'y'` 、`'both'` 、`'none'`。

ipadx 和 ipady

  距离值，指定从属部件的内边距。

padx 和 pady

  距离值，指定从属部件的外边距。

side

  合法值为：`'left'`、 `'right'` 、 `'top'`、 `'bottom'`。

### 部件与变量的关联

通过一些特定参数，某些组件（如文本输入组件）的当前设置可直接与应用程序的变量关联。这些参数包括 `variable` 、 `textvariable` 、 `onvalue` 、 `offvalue` 、 `value`。这种关联是双向的：只要这些变量因任何原因发生变化，其关联的部件就会更新以反映新的参数值。

不幸的是，在目前 `tkinter` 的实现代码中，不可能通过 `variable` 或 `textvariable` 参数将任意 Python 变量移交给组件。变量只有是 `tkinter` 中定义的 Variable 类的子类，才能生效。

已经定义了很多有用的 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()` 方法。该方法以下划线开头，表明其为 Python 实现的代码，而非 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 参数的数据类型

anchor

  合法值是罗盘的方位点：`"n"` 、`"ne"` 、`"e"` 、`"se"` 、`"s"` 、`"sw"` 、`"w"` 、`"nw"` 和 `"center"` 。

bitmap

  内置已命名的位图有八个：`'error'`、 `'gray25'` 、`'gray50'` 、`'hourglass'`、 `'info'` 、`'questhead'` 、`'question'` 、`'warning'` 。若要指定位图的文件名，请给出完整路径，前面加一个 `@`，比如 `"@/usr/contrib/bitmap/gumby.bit"`。

boolean

  可以传入整数 0 或 1，或是字符串 `"yes"` 或 `"no"`。

callback -- 回调

  指任何无需调用参数的 Python 函数。 例如：

      def print_it():
          print("hi there")
      fred["command"] = print_it

color

  可在 rgb.txt 文件中以颜色名的形式给出，或是 RGB 字符串的形式，4 位 ：`"#RGB"` ，8 位 ：`"#RRGGBB"`，12 位：`"#RRRGGGBBB"`，16 位：`"#RRRRGGGGBBBB"`，其中R、G、B 为合法的十六进制数值。 详见 Ousterhout 书中的第 160 页。

cursor

  可采用 `cursorfont.h` 中的标准光标名称，去掉 `XC_` 前缀。 比如要获取一个手形光标（`XC_hand2`），可以用字符串 `"hand2"`。也可以指定自己的位图和掩码文件作为光标。参见 Ousterhout 书中的第 179 页。

distance

  屏幕距离可以用像素或绝对距离来指定。像素是数字，绝对距离是字符串，后面的字符表示单位：`c` 是厘米，`i` 是英寸，`m` 是毫米，`p` 则表示打印机的点数。例如，3.5 英寸可表示为 `"3.5i"`。

font

  Tk 采用一串名称的格式表示字体，例如 `{courier 10 bold}`。正数的字体大小以点为单位，负数的大小以像素为单位。

geometry

  这是一个 `widthxheight` 形式的字符串，其中宽度和高度对于大多数部件来说是以像素为单位的（对于显示文本的部件来说是以字符为单位的）。例如：fred["geometry"] = "200x100"。

justify

  合法的值为字符串： `"left"` 、 `"center"` 、 `"right"` 和 `"fill"` 。

区域

  这是包含四个元素的字符串，以空格分隔，每个元素是表示一个合法的距离值（见上文）。例如：`"2 3 4 5"` 、 `"3i 2i 4.5i 2i"` 和 `"3c 2c 4c 10.43c"` 都是合法的区域值。

relief

  决定了组件的边框样式。 合法值包括：`"raised"`、 `"sunken"` 、`"flat"` 、`"groove"` 和 `"ridge"` 。

scrollcommand

  这几乎就是带滚动条部件的 `set()` 方法，但也可是任一只有一个参数的部件方法。

wrap

  只能是以下值之一：`"none"` 、 `"char"` 、 `"word"`。

### 绑定和事件

部件命令中的 bind 方法可觉察某些事件，并在事件发生时触发一个回调函数。bind 方法的形式是：

    def bind(self, sequence, func, add=''):

其中：

sequence

  是一个表示事件的目标种类的字符串。（详情请看 bind 的手册页和 John Outsterhout 的书的第 201 页。）

func

  是带有一个参数的 Python 函数，发生事件时将会调用。传入的参数为一个 Event 实例。（以这种方式部署的函数通常称为 回调函数。）

add

  可选项， `''` 或 `'+'` 。传入空字符串表示本次绑定将替换与此事件关联的其他所有绑定。传递 `'+'` 则意味着加入此事件类型已绑定函数的列表中。

例如：

    def turn_red(self, event):
        event.widget["activeforeground"] = "red"

    self.button.bind("<Enter>", self.turn_red)

请注意，在 `turn_red()` 回调函数中如何访问事件的 widget 字段。该字段包含了捕获 X 事件的控件。下表列出了事件可供访问的其他字段，及其在 Tk 中的表示方式，这在查看 Tk 手册时很有用处。

Tk | Tkinter 事件字段 | Tk | Tkinter 事件字段
--- | --- | --- | ---
%f | focus | %A | char
%h | height | %E | send_event
%k | keycode | %K | keysym
%s | state | %N | keysym_num
%t | time | %T | type
%w | width | %W | widget
%x | x | %X | x_root
%y | y | %Y | y_root

### index 参数

很多控件都需要传入 index 参数。该参数用于指明 Text 控件中的位置，或指明 Entry 控件中的字符，或指明 Menu 控件中的菜单项。

Entry 控件的索引（index、view index 等）

  Entry 控件带有索引属性，指向显示文本中的字符位置。这些 `tkinter` 函数可用于访问文本控件中的这些特定位置：

Text 控件的索引

  Text 控件的索引语法非常复杂，最好还是在 Tk 手册中查看。

Menu 索引（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 会在用到图片对象的地方显示一个空白框。

也參考

Pillow 包增加了对 BMP、JPEG、TIFF 和 WebP 等格式的支持。

## 文件处理程序

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 参数是下述三个常量的逻辑“或”组合。回调函数将用以下格式调用：

      callback(file, mask)

`Widget.tk.``deletefilehandler`(file)

  注销文件处理函数。

`tkinter.``READABLE`
`tkinter.``WRITABLE`
`tkinter.``EXCEPTION`

  Constants used in the mask arguments.