tkinter
—— Tcl/Tk 的 Python 接口¶
The tkinter
package ("Tk interface") is the standard Python interface to
the Tcl/Tk GUI toolkit. Both Tk and tkinter
are available on most Unix
platforms, including macOS, as well as on Windows systems.
若在命令行执行 python -m tkinter
,应会弹出一个简单的 Tk 界面窗口, 表明 tkinter
包已安装完成,还会显示当前安装的 Tcl/Tk 版本,以便阅读对应版本的 Tcl/Tk 文档。
Tkinter 支持众多的 Tcl/Tk 版本,带或不带多线程版本均可。官方的 Python 二进制版本捆绑了 Tcl/Tk 8.6 多线程版本。关于可支持版本的更多信息,请参阅 _tkinter
模块的源代码。
Tkinter 并不只是做了简单的封装,而是增加了相当多的代码逻辑,让使用体验更具 Python 风格(pythonic) 。本文将集中介绍这些增加和变化部分,关于未改动部分的细节,请参考 Tcl/Tk 官方文档。
备注
Tcl/Tk 8.5 (2007) introduced a modern set of themed user interface components along with a new API to use them. Both old and new APIs are still available. Most documentation you will find online still uses the old API and can be woefully outdated.
参见
- TkDocs
Extensive tutorial on creating user interfaces with Tkinter. Explains key concepts, and illustrates recommended approaches using the modern API.
- Tkinter 8.5 参考手册:一种 Python GUI
Reference documentation for Tkinter 8.5 detailing available classes, methods, and options.
Tcl/Tk Resources:
- Tk 命令
Comprehensive reference to each of the underlying Tcl/Tk commands used by Tkinter.
- Tcl/Tk Home Page
Additional documentation, and links to Tcl/Tk core development.
Books:
- Modern Tkinter for Busy Python Developers
By Mark Roseman. (ISBN 978-1999149567)
- Python and Tkinter Programming
By Alan Moore. (ISBN 978-1788835886)
- 使用 Python 编程
By Mark Lutz; has excellent coverage of Tkinter. (ISBN 978-0596158101)
- Tcl and the Tk Toolkit (2nd edition)
By John Ousterhout, inventor of Tcl/Tk, and Ken Jones; does not cover Tkinter. (ISBN 978-0321336330)
架构¶
Tcl/Tk is not a single library but rather consists of a few distinct modules, each with separate functionality and its own official documentation. Python's binary releases also ship an add-on module together with it.
- Tcl
Tcl 是一种动态解释型编程语言,正如 Python 一样。尽管它可作为一种通用的编程语言单独使用,但最常见的用法还是作为脚本引擎或 Tk 工具包的接口嵌入到 C 程序中。Tcl 库有一个 C 接口,用于创建和管理一个或多个 Tcl 解释器实例,并在这些实例中运行 Tcl 命令和脚本,添加用 Tcl 或 C 语言实现的自定义命令。每个解释器都拥有一个事件队列,某些部件可向解释器发送事件交由其处理。与 Python 不同,Tcl 的执行模型是围绕协同多任务而设计的,Tkinter 协调了两者的差别(详见 Threading model )。
- Tk
Tk 是用 C 语言实现的 Tcl 包,加入了创建和操作 GUI 部件的自定义命令。每个
Tk
对象都嵌入了自己的 Tcl 解释器实例,并载入 Tk 。Tk 的部件是可高度自定义的,不过代价是过时的外观。Tk 利用 Tcl 的事件队列来生成并处理 GUI 事件。- Ttk
带有主题的 Tk(Ttk)是较新加入的 Tk 部件,相比很多经典的 Tk 部件,在各平台提供的界面更加美观。自 Tk 8.5 版本开始,Ttk 作为 Tk 的成员进行发布。Python 则捆绑在一个单独的模块中,
tkinter.ttk
。
Internally, Tk and Ttk use facilities of the underlying operating system, i.e., Xlib on Unix/X11, Cocoa on macOS, GDI on Windows.
When your Python application uses a class in Tkinter, e.g., to create a widget,
the tkinter
module first assembles a Tcl/Tk command string. It passes that
Tcl command string to an internal _tkinter
binary module, which then
calls the Tcl interpreter to evaluate it. The Tcl interpreter will then call into the
Tk and/or Ttk packages, which will in turn make calls to Xlib, Cocoa, or GDI.
Tkinter 模块¶
Support for Tkinter is spread across several modules. Most applications will need the
main tkinter
module, as well as the tkinter.ttk
module, which provides
the modern themed widget set and API:
from tkinter import *
from tkinter import ttk
- class tkinter.Tk(screenName=None, baseName=None, className='Tk', useTk=True, sync=False, use=None)¶
Construct a toplevel Tk widget, which is usually the main window of an application, and initialize a Tcl interpreter for this widget. Each instance has its own associated Tcl interpreter.
The
Tk
class is typically instantiated using all default values. However, the following keyword arguments are currently recognized:- screenName
When given (as a string), sets the
DISPLAY
environment variable. (X11 only)- baseName
Name of the profile file. By default, baseName is derived from the program name (
sys.argv[0]
).- className
Name of the widget class. Used as a profile file and also as the name with which Tcl is invoked (argv0 in interp).
- useTk
If
True
, initialize the Tk subsystem. Thetkinter.Tcl()
function sets this toFalse
.- sync
If
True
, execute all X server commands synchronously, so that errors are reported immediately. Can be used for debugging. (X11 only)- use
Specifies the id of the window in which to embed the application, instead of it being created as an independent toplevel window. id must be specified in the same way as the value for the -use option for toplevel widgets (that is, it has a form like that returned by
winfo_id()
).Note that on some platforms this will only work correctly if id refers to a Tk frame or toplevel that has its -container option enabled.
Tk
reads and interprets profile files, named.className.tcl
and.baseName.tcl
, into the Tcl interpreter and callsexec()
on the contents of.className.py
and.baseName.py
. The path for the profile files is theHOME
environment variable or, if that isn't defined, thenos.curdir
.- tk¶
The Tk application object created by instantiating
Tk
. This provides access to the Tcl interpreter. Each widget that is attached the same instance ofTk
has the same value for itstk
attribute.
- master¶
The widget object that contains this widget. For
Tk
, the master isNone
because it is the main window. The terms master and parent are similar and sometimes used interchangeably as argument names; however, callingwinfo_parent()
returns a string of the widget name whereasmaster
returns the object. parent/child reflects the tree-like relationship while master/slave reflects the container structure.
- tkinter.Tcl(screenName=None, baseName=None, className='Tk', useTk=False)¶
Tcl()
函数是一个工厂函数,它创建的对象类似于Tk
类创建的,只是不会初始化 Tk 子系统。这在调动 Tcl 解释器时最为有用,这时不想创建多余的顶层窗口,或者无法创建(比如不带 X 服务的 Unix/Linux 系统)。由Tcl()
创建的对象可调用loadtk()
方法创建一个顶层窗口(且会初始化 Tk 子系统)。
The modules that provide Tk support include:
tkinter
Main Tkinter module.
tkinter.colorchooser
让用户选择颜色的对话框。
tkinter.commondialog
本文其他模块定义的对话框的基类。
tkinter.filedialog
允许用户指定文件的通用对话框,用于打开或保存文件。
tkinter.font
帮助操作字体的工具。
tkinter.messagebox
访问标准的 Tk 对话框。
tkinter.scrolledtext
内置纵向滚动条的文本组件。
tkinter.simpledialog
基础对话框和一些便捷功能。
tkinter.ttk
Themed widget set introduced in Tk 8.5, providing modern alternatives for many of the classic widgets in the main
tkinter
module.
Additional modules:
_tkinter
A binary module that contains the low-level interface to Tcl/Tk. It is automatically imported by the main
tkinter
module, and should never be used directly by application programmers. It is usually a shared library (or DLL), but might in some cases be statically linked with the Python interpreter.idlelib
Python's Integrated Development and Learning Environment (IDLE). Based on
tkinter
.tkinter.constants
Symbolic constants that can be used in place of strings when passing various parameters to Tkinter calls. Automatically imported by the main
tkinter
module.tkinter.dnd
(experimental) Drag-and-drop support for
tkinter
. This will become deprecated when it is replaced with the Tk DND.tkinter.tix
(deprecated) An older third-party Tcl/Tk package that adds several new widgets. Better alternatives for most can be found in
tkinter.ttk
.turtle
Tk 窗口中的海龟绘图库。
Tkinter 拾遗¶
This section is not designed to be an exhaustive tutorial on either Tk or Tkinter. For that, refer to one of the external resources noted earlier. Instead, this section provides a very quick orientation to what a Tkinter application looks like, identifies foundational Tk concepts, and explains how the Tkinter wrapper is structured.
The remainder of this section will help you to identify the classes, methods, and options you'll need in your Tkinter application, and where to find more detailed documentation on them, including in the official Tcl/Tk reference manual.
A Hello World Program¶
We'll start by walking through a "Hello World" application in Tkinter. This isn't the smallest one we could write, but has enough to illustrate some key concepts you'll need to know.
from tkinter import *
from tkinter import ttk
root = Tk()
frm = ttk.Frame(root, padding=10)
frm.grid()
ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
root.mainloop()
After the imports, the next line creates an instance of the Tk
class,
which initializes Tk and creates its associated Tcl interpreter. It also
creates a toplevel window, known as the root window, which serves as the main
window of the application.
The following line creates a frame widget, which in this case will contain a label and a button we'll create next. The frame is fit inside the root window.
The next line creates a label widget holding a static text string. The
grid()
method is used to specify the relative layout (position) of the
label within its containing frame widget, similar to how tables in HTML work.
A button widget is then created, and placed to the right of the label. When
pressed, it will call the destroy()
method of the root window.
Finally, the mainloop()
method puts everything on the display, and
responds to user input until the program terminates.
Important Tk Concepts¶
Even this simple program illustrates the following key Tk concepts:
- widgets
A Tkinter user interface is made up of individual widgets. Each widget is represented as a Python object, instantiated from classes like
ttk.Frame
,ttk.Label
, andttk.Button
.- widget hierarchy
Widgets are arranged in a hierarchy. The label and button were contained within a frame, which in turn was contained within the root window. When creating each child widget, its parent widget is passed as the first argument to the widget constructor.
- configuration options
Widgets have configuration options, which modify their appearance and behavior, such as the text to display in a label or button. Different classes of widgets will have different sets of options.
- geometry management
Widgets aren't automatically added to the user interface when they are created. A geometry manager like
grid
controls where in the user interface they are placed.- event loop
Tkinter reacts to user input, changes from your program, and even refreshes the display only when actively running an event loop. If your program isn't running the event loop, your user interface won't update.
Understanding How Tkinter Wraps Tcl/Tk¶
When your application uses Tkinter's classes and methods, internally Tkinter
is assembling strings representing Tcl/Tk commands, and executing those
commands in the Tcl interpreter attached to your applicaton's Tk
instance.
Whether it's trying to navigate reference documentation, trying to find the right method or option, adapting some existing code, or debugging your Tkinter application, there are times that it will be useful to understand what those underlying Tcl/Tk commands look like.
To illustrate, here is the Tcl/Tk equivalent of the main part of the Tkinter script above.
ttk::frame .frm -padding 10
grid .frm
grid [ttk::label .frm.lbl -text "Hello World!"] -column 0 -row 0
grid [ttk::button .frm.btn -text "Quit" -command "destroy ."] -column 1 -row 0
Tcl's syntax is similar to many shell languages, where the first word is the command to be executed, with arguments to that command following it, separated by spaces. Without getting into too many details, notice the following:
The commands used to create widgets (like
ttk::frame
) correspond to widget classes in Tkinter.Tcl widget options (like
-text
) correspond to keyword arguments in Tkinter.Widgets are referred to by a pathname in Tcl (like
.frm.btn
), whereas Tkinter doesn't use names but object references.A widget's place in the widget hierarchy is encoded in its (hierarchical) pathname, which uses a
.
(dot) as a path separator. The pathname for the root window is just.
(dot). In Tkinter, the hierarchy is defined not by pathname but by specifying the parent widget when creating each child widget.Operations which are implemented as separate commands in Tcl (like
grid
ordestroy
) are represented as methods on Tkinter widget objects. As you'll see shortly, at other times Tcl uses what appear to be method calls on widget objects, which more closely mirror what would is used in Tkinter.
How do I...? What option does...?¶
If you're not sure how to do something in Tkinter, and you can't immediately find it in the tutorial or reference documentation you're using, there are a few strategies that can be helpful.
First, remember that the details of how individual widgets work may vary across different versions of both Tkinter and Tcl/Tk. If you're searching documentation, make sure it corresponds to the Python and Tcl/Tk versions installed on your system.
When searching for how to use an API, it helps to know the exact name of the
class, option, or method that you're using. Introspection, either in an
interactive Python shell or with print()
, can help you identify what
you need.
To find out what configuration options are available on any widget, call its
configure()
method, which returns a dictionary containing a variety of
information about each object, including its default and current values. Use
keys()
to get just the names of each option.
btn = ttk.Button(frm, ...)
print(btn.configure().keys())
As most widgets have many configuration options in common, it can be useful to find out which are specific to a particular widget class. Comparing the list of options to that of a simpler widget, like a frame, is one way to do that.
print(set(btn.configure().keys()) - set(frm.configure().keys()))
Similarly, you can find the available methods for a widget object using the
standard dir()
function. If you try it, you'll see there are over 200
common widget methods, so again identifying those specific to a widget class
is helpful.
print(dir(btn))
print(set(dir(btn)) - set(dir(frm)))
线程模型¶
Python 和 Tcl/Tk 的线程模型大不相同,而 tkinter
则会试图进行调和。若要用到线程,可能需要注意这一点。
一个 Python 解释器可能会关联很多线程。在 Tcl 中,可以创建多个线程,但每个线程都关联了单独的 Tcl 解释器实例。线程也可以创建一个以上的解释器实例,尽管每个解释器实例只能由创建它的那个线程使用。
Each Tk
object created by tkinter
contains a Tcl interpreter.
It also keeps track of which thread created that interpreter. Calls to
tkinter
can be made from any Python thread. Internally, if a call comes
from a thread other than the one that created the Tk
object, an event
is posted to the interpreter's event queue, and when executed, the result is
returned to the calling Python thread.
Tcl/Tk 应用程序通常是事件驱动的,这意味着在完成初始化以后,解释器会运行一个事件循环(即 Tk.mainloop()
)并对事件做出响应。因为它是单线程的,所以事件处理程序必须快速响应,否则会阻塞其他事件的处理。为了避免阻塞,不应在事件处理程序中执行任何耗时很久的计算,而应利用计时器将任务分块,或者在其他线程中运行。而其他很多工具包的 GUI 是在一个完全独立的线程中运行的,独立于包括事件处理程序在内的所有代码。
如果 Tcl 解释器没有运行事件循环并处理解释器事件,则除运行 Tcl 解释器的线程外,任何其他线程发起的 tkinter
调用都会失败。
存在一些特殊情况:
Tcl/Tk 库可编译为不支持多线程的版本。这时
tkinter
会从初始 Python 线程调用底层库,即便那不是创建 Tcl 解释器的线程。会有一个全局锁来确保每次只会发生一次调用。虽然
tkinter
允许创建一个以上的Tk
实例(都带有自己的解释器),但所有属于同一线程的解释器均会共享同一个事件队列,这样很快就会一团糟。在实际编程时,一次创建的Tk
实例不要超过一个。否则最好在不同的线程中创建,并确保运行的是支持多线程的 Tcl/Tk 版本。为了防止 Tcl 解释器重新进入事件循环,阻塞事件处理程序并不是唯一的做法。甚至可以运行多个嵌套的事件循环,或者完全放弃事件循环。如果在处理事件或线程时碰到棘手的问题,请小心这些可能的事情。
有几个
tkinter
函数,目前只在创建 Tcl 解释器的线程中调用才行。
快速参考¶
可选配置项¶
配置参数可以控制组件颜色和边框宽度等。可通过三种方式进行设置:
- 在对象创建时,使用关键字参数
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 |
选项名称 |
|
1 |
数据库查找的选项名称 |
|
2 |
数据库查找的选项类 |
|
3 |
默认值 |
|
4 |
当前值 |
|
示例:
>>> 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
Colors can be given as the names of X colors in the rgb.txt file, or as strings representing RGB values in 4 bit:
"#RGB"
, 8 bit:"#RRGGBB"
, 12 bit:"#RRRGGGBBB"
, or 16 bit:"#RRRRGGGGBBBB"
ranges, where R,G,B here represent any legal hex digit. See page 160 of Ousterhout's book for details.- 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"
。- region
这是包含四个元素的字符串,以空格分隔,每个元素是表示一个合法的距离值(见上文)。例如:
"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
is a string that denotes the target kind of event. (See the bind(3tk) man page, and page 201 of John Ousterhout's book, Tcl and the Tk Toolkit (2nd edition), for details).
- 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)¶
注销文件处理函数。