24.1. Tkinter - Tcl / Tk的Python接口

Tkinter 模块(也称Tk接口)是pyhton用于处理Tk GUI工具集提供的一个标准接口。大多数Unix平台以及Windows系统都可以使用Tk和Tkinter(Tk本身不是Python的一部分;它在ActiveState中维护。)

Note

在Python 3中,Tkinter已重命名为tkinter当您将源转换为Python 3时,2to3工具将自动调整导入。

See also

Python Tkinter Resources
Python Tkinter主题指南提供了大量关于使用Python的Tk和Tk上其他信息源的链接的信息。
TKDocs
广泛的教程和一些小部件的友好的小部件页面。
Tkinter reference: a GUI for Python
在线参考资料。
Tkinter docs from effbot
由fobot.org支持的tkinter的在线参考。
Tcl/Tk manual
最新的tcl / tk版本的官方手册。
Programming Python
由马克·卢茨(Mark Lutz)撰写,具有很好的覆盖面。
Modern Tkinter for Busy Python Developers
通过Mark Rozerman的书面介绍,使用Python和Tkinter构建有吸引力的现代图形用户界面。
Python and Tkinter Programming
约翰·格雷森(John Grayson)的书(ISBN 1-884777-81-3)。

24.1.1. Tkinter模块

大多数情况下,Tkinter模块是您真正需要的,但还有一些其他模块可用。Tk接口位于名为_tkinter的二进制模块中。该模块包含Tk的低级接口,应该不应由应用程序员直接使用。它通常是一个共享库(或DLL),但在某些情况下可能会与Python解释器静态链接。

除了Tk接口模块,Tkinter还包含许多Python模块。两个最重要的模块是Tkinter模块本身,一个名为Tkconstants的模块。前者自动导入后者,所以要使用Tkinter,你需要做的就是导入一个模块:

import Tkinter

Or, more often:

from Tkinter import *
class Tkinter.Tk(screenName=None, baseName=None, className='Tk', useTk=1)

Tk类没有参数被实例化。这创建了一个Tk的顶级小部件,它通常是一个应用程序的主窗口。每个实例都有自己的关联的Tcl解释器。

在版本2.4中更改:添加了useTk参数。

Tkinter.Tcl(screenName=None, baseName=None, className='Tk', useTk=0)

Tcl()函数是一个工厂函数,它创建一个非常类似于Tk类创建的对象,除了它不初始化Tk子系统。在一个不想创建无关的高层窗口的环境中,或者不能使用(如没有X服务器的Unix / Linux系统)的环境中,驱动Tcl解释器时,这通常很有用。Tcl()对象创建的对象可以通过调用其loadtk()方法创建一个Toplevel窗口(并且Tk子系统已初始化)。

New in version 2.4.

提供Tk支持的其他模块包括:

ScrolledText
内置垂直滚动条的文本小部件。
tkColorChooser
对话框让用户选择一种颜色。
tkCommonDialog
在这里列出的其他模块中定义的对话框的基类。
tkFileDialog
通用对话框允许用户指定要打开或保存的文件。
tkFont
帮助使用字体的工具。
tkMessageBox
访问标准Tk对话框。
tkSimpleDialog
基本对话和便利功能。
Tkdnd
拖放支持Tkinter这是实验性的,当它被替换为Tk DND时,应该被弃用。
turtle
海龟图形在Tk窗口。

这些在Python 3中也被重命名了;它们都是新的tkinter包的子模块。

24.1.2. Tkinter Life Preserver

本节不是设计为Tk或Tkinter的详尽教程。相反,这是一个暂时的差距,为系统提供了一些介绍性的方向。

学分:

  • Tkinter由Steen Lumholt和Guido van Rossum撰写。
  • Tk由John Ousterhout在伯克利写的。
  • 这个生命保护者是由弗吉尼亚大学的马特康威(Matt Conway)撰写的。
  • 由Ken Manheimer的FrameMaker版本生成html渲染和一些自由编辑。
  • Fredrik Lundh详细阐述和修改了类接口描述,以便使用Tk 4.2获取它们的最新信息。
  • Mike Clarkson将文档转换为LaTeX,并编制了参考手册的用户界面章节。

24.1.2.1. 如何使用本节

本节设计分为两部分:前半部分(粗略地)涵盖背景材料,而下半部分可以作为方便的参考使用到键盘。

当尝试回答“我如何做blah”的形式的问题时,通常最好在直线Tk中找出如何做“blah”,然后将其转换回相应的Tkinter调用。Python程序员通常可以通过查看Tk文档来猜测正确的Python命令。这意味着为了使用Tkinter,你必须知道一点关于Tk。本文档无法履行该角色,所以我们可以做的最好的事情是指出存在的最佳文档。这里有一些提示:

  • 作者强烈建议获取Tk手册页的副本。具体来说,mann目录中的手册页最有用。man3手册页描述了Tk库的C接口,因此对脚本编写者不是特别有用。
  • Addison-Wesley发行了一本名为Tcl的书籍和John Ousterhout的“Tk工具包”(ISBN 0-201-63337-X),这是Tcl和Tk对新手的一个很好的介绍。这本书并不详尽,对于许多细节,它延伸到手册页。
  • Tkinter.py是大多数人的最后手段,但没有其他意义,可以是一个好地方。

See also

ActiveState Tcl Home Page
Tk / Tcl开发主要发生在ActiveState。
Tcl and the Tk Toolkit
Tcl发明家John Ousterhout的书。
Practical Programming in Tcl and Tk
布伦特·韦尔奇的百科全书。

24.1.2.2. 一个简单的Hello World Program

from Tkinter import *

class Application(Frame):
    def say_hi(self):
        print "hi there, everyone!"

    def createWidgets(self):
        self.QUIT = Button(self)
        self.QUIT["text"] = "QUIT"
        self.QUIT["fg"]   = "red"
        self.QUIT["command"] =  self.quit

        self.QUIT.pack({"side": "left"})

        self.hi_there = Button(self)
        self.hi_there["text"] = "Hello",
        self.hi_there["command"] = self.say_hi

        self.hi_there.pack({"side": "left"})

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.createWidgets()

root = Tk()
app = Application(master=root)
app.mainloop()
root.destroy()

24.1.3. (非常)快速查看Tcl / Tk

类层次结构看起来很复杂,但在实践中,应用程序员几乎总是引用层次结构底层的类。

Notes:

  • 这些类是为了在一个命名空间下组织某些功能而提供的。它们不是要独立实例化。
  • Tk类在应用程序中仅被实例化一次。应用程序员不需要明确实例化,只要任何其他类被实例化,系统就会创建一个。
  • Widget类不是要实例化的,它仅用于子类化以创建“实际”小部件(在C中,这被称为“抽象类”)。

为了使用这个参考资料,你将需要知道如何阅读Tk的简短段落以及如何识别Tk命令的各个部分。(参见将基本Tk映射到Tkinter中的Tkinter等效于下面的内容。)

Tk脚本是Tcl程序。像所有Tcl程序一样,Tk脚本只是用空格分隔的令牌列表。一个Tk小部件就是它的,有助于配置它的选项以及使它变得有用的动作

要在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 ...)

创建后,窗口小部件的路径名将成为新的命令。这个新的小部件命令是程序员的手柄,用于获取新的小部件来执行一些动作在C中,你会把这个表达为someAction(fred,someOptions),在C中,你会将其表示为fred.someAction(someOptions),在Tk中你会说:

.fred someAction someOptions

请注意,对象名称.fred以点开头。

正如你所料,someAction的合法值将取决于小部件的类:.fred disable如果fred是一个按钮(fred变灰),但是如果fred是标签,则不起作用(Tk中不支持禁用标签)。

The legal values of someOptions is action dependent. 某些操作(如disable)不需要任何参数,其他操作(如文本输入框的delete命令)将需要参数来指定要删除的文本范围。

24.1.4. Mapping Basic Tk into 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中,要对窗口小部件执行操作,请使用窗口小部件名称作为命令,并使用动作名称(可能使用参数(选项))来跟踪它。在Tkinter中,您可以调用类实例上的方法来调用窗口小部件上的操作。Tkinter.py模块中列出了一个给定的窗口小部件可以执行的动作(方法)。

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

要给封装器(几何管理器)提供一个小部件,你可以使用可选参数来调用pack。在Tkinter中,Pack类保存所有这些功能,并且pack命令的各种形式被实现为方法。Tkinter中的所有小部件都从封隔器进行子类化,因此继承了所有打包方法。有关Form几何管理器的其他信息,请参阅Tix模块文档。

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

24.1.6. Handy Reference

24.1.6.1. Setting Options

Options control things like the color and border width of a widget. Options can be set in three ways:

At object creation time, using keyword arguments
fred = Button(self, fg = "red", bg = "blue")
After object creation, treating the option name like a dictionary index
fred["fg"] = "red"
fred["bg"] = "blue"
Use the config() method to update multiple attrs subsequent to object creation
fred.config(fg = "red", bg = "blue")

For a complete explanation of a given option and its behavior, see the Tk man pages for the widget in question.

Note that the man pages list “STANDARD OPTIONS” and “WIDGET SPECIFIC OPTIONS” for each widget. The former is a list of options that are common to many widgets, the latter are the options that are idiosyncratic to that particular widget. The Standard Options are documented on the options(3) man page.

No distinction between standard and widget-specific options is made in this document. Some options don’t apply to some kinds of widgets. Whether a given widget responds to a particular option depends on the class of the widget; buttons have a command option, labels do not.

The options supported by a given widget are listed in that widget’s man page, or can be queried at runtime by calling the config() method without arguments, or by calling the keys() method on that widget. The return value of these calls is a dictionary whose key is the name of the option as a string (for example, 'relief') and whose values are 5-tuples.

Some options, like bg are synonyms for common options with long names (bg is shorthand for “background”). Passing the config() method the name of a shorthand option will return a 2-tuple, not 5-tuple. The 2-tuple passed back will contain the name of the synonym and the “real” option (such as ('bg', 'background')).

IndexMeaningExample
0option name'relief'
1option name for database lookup'relief'
2option class for database lookup'Relief'
3default value'raised'
4current value'groove'

Example:

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

Of course, the dictionary printed will include all the options available and their values. This is meant only as an example.

24.1.6.2. The Packer

The packer is one of Tk’s geometry-management mechanisms. Geometry managers are used to specify the relative positioning of the positioning of widgets within their container - their mutual master. In contrast to the more cumbersome placer (which is used less commonly, and we do not cover here), the packer takes qualitative relationship specification - above, to the left of, filling, etc - and works everything out to determine the exact placement coordinates for you.

The size of any master widget is determined by the size of the “slave widgets” inside. The packer is used to control where slave widgets appear inside the master into which they are packed. You can pack widgets into frames, and frames into other frames, in order to achieve the kind of layout you desire. Additionally, the arrangement is dynamically adjusted to accommodate incremental changes to the configuration, once it is packed.

Note that widgets do not appear until they have had their geometry specified with a geometry manager. It’s a common early mistake to leave out the geometry specification, and then be surprised when the widget is created but nothing appears. A widget will appear only after it has had, for example, the packer’s pack() method applied to it.

The pack() method can be called with keyword-option/value pairs that control where the widget is to appear within its container, and how it is to behave when the main application window is resized. Here are some examples:

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

24.1.6.3. Packer Options

For more extensive information on the packer and the options that it can take, see the man pages and page 183 of John Ousterhout’s book.

anchor
Anchor type. Denotes where the packer is to place each slave in its parcel.
expand
Boolean, 0 or 1.
fill
Legal values: 'x', 'y', 'both', 'none'.
ipadx and ipady
A distance - designating internal padding on each side of the slave widget.
padx and pady
A distance - designating external padding on each side of the slave widget.
side
Legal values are: 'left', 'right', 'top', 'bottom'.

24.1.6.4. Coupling Widget Variables

The current-value setting of some widgets (like text entry widgets) can be connected directly to application variables by using special options. These options are variable, textvariable, onvalue, offvalue, and value. This connection works both ways: if the variable changes for any reason, the widget it’s connected to will be updated to reflect the new value.

Unfortunately, in the current implementation of Tkinter it is not possible to hand over an arbitrary Python variable to a widget through a variable or textvariable option. The only kinds of variables for which this works are variables that are subclassed from a class called Variable, defined in the Tkinter module.

There are many useful subclasses of Variable already defined: StringVar, IntVar, DoubleVar, and BooleanVar. To read the current value of such a variable, call the get() method on it, and to change its value you call the set() method. If you follow this protocol, the widget will always track the value of the variable, with no further intervention on your part.

For example:

class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()

        self.entrythingy = Entry()
        self.entrythingy.pack()

        # here is the application variable
        self.contents = 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

        # and here we get a callback when the user hits return.
        # we will have the program print out the value of the
        # application variable when the user hits return
        self.entrythingy.bind('<Key-Return>',
                              self.print_contents)

    def print_contents(self, event):
        print "hi. contents of entry is now ---->", \
              self.contents.get()

24.1.6.5. The Window Manager

In Tk, there is a utility command, wm, for interacting with the window manager. Options to the wm command allow you to control things like titles, placement, icon bitmaps, and the like. In Tkinter, these commands have been implemented as methods on the Wm class. Toplevel widgets are subclassed from the Wm class, and so can call the Wm methods directly.

To get at the toplevel window that contains a given widget, you can often just refer to the widget’s master. Of course if the widget has been packed inside of a frame, the master won’t represent a toplevel window. To get at the toplevel window that contains an arbitrary widget, you can call the _root() method. This method begins with an underscore to denote the fact that this function is part of the implementation, and not an interface to Tk functionality.

Here are some examples of typical usage:

from Tkinter import *
class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, 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()

24.1.6.6. Tk Option Data Types

anchor
Legal values are points of the compass: "n", "ne", "e", "se", "s", "sw", "w", "nw", and also "center".
bitmap
There are eight built-in, named bitmaps: 'error', 'gray25', 'gray50', 'hourglass', 'info', 'questhead', 'question', 'warning'. To specify an X bitmap filename, give the full path to the file, preceded with an @, as in "@/usr/contrib/bitmap/gumby.bit".
boolean
You can pass integers 0 or 1 or the strings "yes" or "no".
callback

This is any Python function that takes no arguments. For example:

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
The standard X cursor names from cursorfont.h can be used, without the XC_ prefix. For example to get a hand cursor (XC_hand2), use the string "hand2". You can also specify a bitmap and mask file of your own. See page 179 of Ousterhout’s book.
distance
Screen distances can be specified in either pixels or absolute distances. Pixels are given as numbers and absolute distances as strings, with the trailing character denoting units: c for centimetres, i for inches, m for millimetres, p for printer’s points. For example, 3.5 inches is expressed as "3.5i".
font
Tk uses a list font name format, such as {courier 10 bold}. Font sizes with positive numbers are measured in points; sizes with negative numbers are measured in pixels.
geometry
This is a string of the form widthxheight, where width and height are measured in pixels for most widgets (in characters for widgets displaying text). For example: fred["geometry"] = "200x100".
justify
Legal values are the strings: "left", "center", "right", and "fill".
region
This is a string with four space-delimited elements, each of which is a legal distance (see above). For example: "2 3 4 5" and "3i 2i 4.5i 2i" and "3c 2c 4c 10.43c" are all legal regions.
relief
Determines what the border style of a widget will be. Legal values are: "raised", "sunken", "flat", "groove", and "ridge".
scrollcommand
This is almost always the set() method of some scrollbar widget, but can be any widget method that takes a single argument. Refer to the file Demo/tkinter/matt/canvas-with-scrollbars.py in the Python source distribution for an example.
wrap:
Must be one of: "none", "char", or "word".

24.1.6.7. Bindings and Events

The bind method from the widget command allows you to watch for certain events and to have a callback function trigger when that event type occurs. The form of the bind method is:

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

where:

sequence
is a string that denotes the target kind of event. (See the bind man page and page 201 of John Ousterhout’s book for details).
func
is a Python function, taking one argument, to be invoked when the event occurs. An Event instance will be passed as the argument. (Functions deployed this way are commonly known as callbacks.)
add
is optional, either '' or '+'. Passing an empty string denotes that this binding is to replace any other bindings that this event is associated with. Passing a '+' means that this function is to be added to the list of functions bound to this event type.

For example:

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

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

Notice how the widget field of the event is being accessed in the turnRed() callback. This field contains the widget that caught the X event. The following table lists the other event fields you can access, and how they are denoted in Tk, which can be useful when referring to the Tk man pages.

Tk      Tkinter Event Field             Tk      Tkinter Event Field
--      -------------------             --      -------------------
%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

24.1.6.8. The index Parameter

A number of widgets require”index” parameters to be passed. These are used to point at a specific place in a Text widget, or to particular characters in an Entry widget, or to particular menu items in a Menu widget.

Entry widget indexes (index, view index, etc.)

Entry widgets have options that refer to character positions in the text being displayed. You can use these Tkinter functions to access these special points in text widgets:

AtEnd()
refers to the last position in the text
AtInsert()
refers to the point where the text cursor is
AtSelFirst()
indicates the beginning point of the selected text
AtSelLast()
denotes the last point of the selected text and finally
At(x[, y])
refers to the character at pixel location x, y (with y not used in the case of a text entry widget, which contains a single line of text).
Text widget indexes
The index notation for Text widgets is very rich and is best described in the Tk man pages.
Menu indexes (menu.invoke(), menu.entryconfig(), etc.)

Some options and methods for menus manipulate specific menu entries. Anytime a menu index is needed for an option or a parameter, you may pass in:

  • an integer which refers to the numeric position of the entry in the widget, counted from the top, starting with 0;
  • the string 'active', which refers to the menu position that is currently under the cursor;
  • the string "last" which refers to the last menu item;
  • An integer preceded by @, as in @6, where the integer is interpreted as a y pixel coordinate in the menu’s coordinate system;
  • the string "none", which indicates no menu entry at all, most often used with menu.activate() to deactivate all entries, and finally,
  • a text string that is pattern matched against the label of the menu entry, as scanned from the top of the menu to the bottom. Note that this index type is considered after all the others, which means that matches for menu items labelled last, active, or none may be interpreted as the above literals, instead.

24.1.6.9. Images

Bitmap/Pixelmap images can be created through the subclasses of Tkinter.Image:

  • BitmapImage can be used for X11 bitmap data.
  • PhotoImage can be used for GIF and PPM/PGM color bitmaps.

Either type of image is created through either the file or the data option (other options are available as well).

The image object can then be used wherever an image option is supported by some widget (e.g. labels, buttons, menus). In these cases, Tk will not keep a reference to the image. When the last Python reference to the image object is deleted, the image data is deleted as well, and Tk will display an empty box wherever the image was used.