tkinter —— Tcl/Tk 的 Python 接口?

源代碼: Lib/tkinter/__init__.py


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,應會(huì )彈出一個(gè)簡(jiǎn)單的 Tk 界面窗口, 表明 tkinter 包已安裝完成,還會(huì )顯示當前安裝的 Tcl/Tk 版本,以便閱讀對應版本的 Tcl/Tk 文檔。

Tkinter 支持眾多的 Tcl/Tk 版本,帶或不帶多線(xiàn)程版本均可。官方的 Python 二進(jìn)制版本捆綁了 Tcl/Tk 8.6 多線(xiàn)程版本。關(guān)于可支持版本的更多信息,請參閱 _tkinter 模塊的源代碼。

Tkinter 并不只是做了簡(jiǎn)單的封裝,而是增加了相當多的代碼邏輯,讓使用體驗更具 Python 風(fēng)格(pythonic) 。本文將集中介紹這些增加和變化部分,關(guān)于未改動(dòng)部分的細節,請參考 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.

參見(jiàn)

  • 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:

架構?

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 是一種動(dòng)態(tài)解釋型編程語(yǔ)言,正如 Python 一樣。盡管它可作為一種通用的編程語(yǔ)言單獨使用,但最常見(jiàn)的用法還是作為腳本引擎或 Tk 工具包的接口嵌入到 C 程序中。Tcl 庫有一個(gè) C 接口,用于創(chuàng )建和管理一個(gè)或多個(gè) Tcl 解釋器實(shí)例,并在這些實(shí)例中運行 Tcl 命令和腳本,添加用 Tcl 或 C 語(yǔ)言實(shí)現的自定義命令。每個(gè)解釋器都擁有一個(gè)事件隊列,某些部件可向解釋器發(fā)送事件交由其處理。與 Python 不同,Tcl 的執行模型是圍繞協(xié)同多任務(wù)而設計的,Tkinter 協(xié)調了兩者的差別(詳見(jiàn) Threading model )。

Tk

Tk 是用 C 語(yǔ)言實(shí)現的 Tcl 包,加入了創(chuàng )建和操作 GUI 部件的自定義命令。每個(gè) Tk 對象都嵌入了自己的 Tcl 解釋器實(shí)例,并載入 Tk 。Tk 的部件是可高度自定義的,不過(guò)代價(jià)是過(guò)時(shí)的外觀(guān)。Tk 利用 Tcl 的事件隊列來(lái)生成并處理 GUI 事件。

Ttk

帶有主題的 Tk(Ttk)是較新加入的 Tk 部件,相比很多經(jīng)典的 Tk 部件,在各平臺提供的界面更加美觀(guān)。自 Tk 8.5 版本開(kāi)始,Ttk 作為 Tk 的成員進(jìn)行發(fā)布。Python 則捆綁在一個(gè)單獨的模塊中, 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. The tkinter.Tcl() function sets this to False.

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 calls exec() on the contents of .className.py and .baseName.py. The path for the profile files is the HOME environment variable or, if that isn't defined, then os.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 of Tk has the same value for its tk attribute.

master?

The widget object that contains this widget. For Tk, the master is None because it is the main window. The terms master and parent are similar and sometimes used interchangeably as argument names; however, calling winfo_parent() returns a string of the widget name whereas master returns the object. parent/child reflects the tree-like relationship while master/slave reflects the container structure.

children?

The immediate descendants of this widget as a dict with the child widget names as the keys and the child instance objects as the values.

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

Tcl() 函數是一個(gè)工廠(chǎng)函數,它創(chuàng )建的對象類(lèi)似于 Tk 類(lèi)創(chuàng )建的,只是不會(huì )初始化 Tk 子系統。這在調動(dòng) Tcl 解釋器時(shí)最為有用,這時(shí)不想創(chuàng )建多余的頂層窗口,或者無(wú)法創(chuàng )建(比如不帶 X 服務(wù)的 Unix/Linux 系統)。由 Tcl() 創(chuàng )建的對象可調用 loadtk() 方法創(chuàng )建一個(gè)頂層窗口(且會(huì )初始化 Tk 子系統)。

The modules that provide Tk support include:

tkinter

Main Tkinter module.

tkinter.colorchooser

讓用戶(hù)選擇顏色的對話(huà)框。

tkinter.commondialog

本文其他模塊定義的對話(huà)框的基類(lèi)。

tkinter.filedialog

允許用戶(hù)指定文件的通用對話(huà)框,用于打開(kāi)或保存文件。

tkinter.font

幫助操作字體的工具。

tkinter.messagebox

訪(fǎng)問(wèn)標準的 Tk 對話(huà)框。

tkinter.scrolledtext

內置縱向滾動(dòng)條的文本組件。

tkinter.simpledialog

基礎對話(huà)框和一些便捷功能。

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, and ttk.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 or destroy) 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)))

線(xiàn)程模型?

Python 和 Tcl/Tk 的線(xiàn)程模型大不相同,而 tkinter 則會(huì )試圖進(jìn)行調和。若要用到線(xiàn)程,可能需要注意這一點(diǎn)。

一個(gè) Python 解釋器可能會(huì )關(guān)聯(lián)很多線(xiàn)程。在 Tcl 中,可以創(chuàng )建多個(gè)線(xiàn)程,但每個(gè)線(xiàn)程都關(guān)聯(lián)了單獨的 Tcl 解釋器實(shí)例。線(xiàn)程也可以創(chuàng )建一個(gè)以上的解釋器實(shí)例,盡管每個(gè)解釋器實(shí)例只能由創(chuàng )建它的那個(gè)線(xiàn)程使用。

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 應用程序通常是事件驅動(dòng)的,這意味著(zhù)在完成初始化以后,解釋器會(huì )運行一個(gè)事件循環(huán)(即 Tk.mainloop())并對事件做出響應。因為它是單線(xiàn)程的,所以事件處理程序必須快速響應,否則會(huì )阻塞其他事件的處理。為了避免阻塞,不應在事件處理程序中執行任何耗時(shí)很久的計算,而應利用計時(shí)器將任務(wù)分塊,或者在其他線(xiàn)程中運行。而其他很多工具包的 GUI 是在一個(gè)完全獨立的線(xiàn)程中運行的,獨立于包括事件處理程序在內的所有代碼。

如果 Tcl 解釋器沒(méi)有運行事件循環(huán)并處理解釋器事件,則除運行 Tcl 解釋器的線(xiàn)程外,任何其他線(xiàn)程發(fā)起的 tkinter 調用都會(huì )失敗。

存在一些特殊情況:

  • Tcl/Tk 庫可編譯為不支持多線(xiàn)程的版本。這時(shí) tkinter 會(huì )從初始 Python 線(xiàn)程調用底層庫,即便那不是創(chuàng )建 Tcl 解釋器的線(xiàn)程。會(huì )有一個(gè)全局鎖來(lái)確保每次只會(huì )發(fā)生一次調用。

  • 雖然 tkinter 允許創(chuàng )建一個(gè)以上的 Tk 實(shí)例(都帶有自己的解釋器),但所有屬于同一線(xiàn)程的解釋器均會(huì )共享同一個(gè)事件隊列,這樣很快就會(huì )一團糟。在實(shí)際編程時(shí),一次創(chuàng )建的 Tk 實(shí)例不要超過(guò)一個(gè)。否則最好在不同的線(xiàn)程中創(chuàng )建,并確保運行的是支持多線(xiàn)程的 Tcl/Tk 版本。

  • 為了防止 Tcl 解釋器重新進(jìn)入事件循環(huán),阻塞事件處理程序并不是唯一的做法。甚至可以運行多個(gè)嵌套的事件循環(huán),或者完全放棄事件循環(huán)。如果在處理事件或線(xiàn)程時(shí)碰到棘手的問(wèn)題,請小心這些可能的事情。

  • 有幾個(gè) tkinter 函數,目前只在創(chuàng )建 Tcl 解釋器的線(xiàn)程中調用才行。

快速參考?

可選配置項?

配置參數可以控制組件顏色和邊框寬度等??赏ㄟ^(guò)三種方式進(jìn)行設置:

在對象創(chuàng )建時(shí),使用關(guān)鍵字參數
fred = Button(self, fg="red", bg="blue")
在對象創(chuàng )建后,將參數名用作字典索引
fred["fg"] = "red"
fred["bg"] = "blue"
利用 config() 方法修改對象的多個(gè)屬性
fred.config(fg="red", bg="blue")

關(guān)于這些參數及其表現的完整解釋?zhuān)垍㈤?Tk 手冊中有關(guān)組件的 man 幫助頁(yè)。

請注意,man 手冊頁(yè)列出了每個(gè)部件的“標準選項”和“組件特有選項”。前者是很多組件通用的選項列表,后者是該組件特有的選項。標準選項在 options(3) man 手冊中有文檔。

本文沒(méi)有區分標準選項和部件特有選項。有些選項不適用于某類(lèi)組件。組件是否對某選項做出響應,取決于組件的類(lèi)別;按鈕組件有一個(gè) command 選項,而標簽組件就沒(méi)有。

組件支持的選項在其手冊中有列出,也可在運行時(shí)調用 config() 方法(不帶參數)查看,或者通過(guò)調用組件的 keys() 方法進(jìn)行查詢(xún)。這些調用的返回值為字典,字典的鍵是字符串格式的選項名(比如 'relief'),字典的值為五元組。

有些選項,比如 bg 是全名通用選項的同義詞(bg 是 “background”的簡(jiǎn)寫(xiě))。向 config() 方法傳入選項的簡(jiǎn)稱(chēng)將返回一個(gè)二元組,而不是五元組。傳回的二元組將包含同義詞的全名和“真正的”選項(比如 ('bg', 'background'))。

索引

含意

示例

0

選項名稱(chēng)

'relief'

1

數據庫查找的選項名稱(chēng)

'relief'

2

數據庫查找的選項類(lèi)

'Relief'

3

默認值

'raised'

4

當前值

'groove'

示例:

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

當然,輸出的字典將包含所有可用選項及其值。這里只是舉個(gè)例子。

包裝器?

包裝器是 Tk 的形狀管理機制之一。 形狀(geometry )管理器用于指定多個(gè)部件在容器(共同的 組件)內的相對位置。與更為麻煩的 定位器 相比(不太常用,這里不做介紹),包裝器可接受定性的相對關(guān)系—— 上面 、左邊 、填充 等,并確定精確的位置坐標。

部件的大小都由其內部的 “從屬部件” 的大小決定。包裝器用于控制從屬部件在主部件中出現的位置??梢园巡考肟蚣?,再把框架包入其他框架中,搭建出所需的布局。此外,只要完成了包裝,組件的布局就會(huì )進(jìn)行動(dòng)態(tài)調整,以適應布局參數的變化。

請注意,只有用形狀管理器指定幾何形狀后,部件才會(huì )顯示出來(lái)。忘記設置形狀參數是新手常犯的錯誤,驚訝于創(chuàng )建完部件卻啥都沒(méi)出現。部件只有在應用了類(lèi)似于打包器的 pack() 方法之后才會(huì )顯示在屏幕上。

調用 pack() 方法時(shí)可以給出由關(guān)鍵字/參數值組成的鍵值對,以便控制組件在其容器中出現的位置,以及主程序窗口大小變動(dòng)時(shí)的行為。下面是一些例子:

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

包裝器的參數?

關(guān)于包裝器及其可接受的參數,更多信息請參閱 man 手冊和 John Ousterhout 書(shū)中的第 183 頁(yè)。

anchor

anchor 類(lèi)型。 表示包裝器要放置的每個(gè)從屬組件的位置。

expand

布爾型,01 。

fill

合法值為:'x' 、'y' 、'both' 、'none'。

ipadx 和 ipady

距離值,指定從屬部件的內邊距。

padx 和 pady

距離值,指定從屬部件的外邊距。

side

合法值為:'left'、 'right' 、 'top'、 'bottom'。

部件與變量的關(guān)聯(lián)?

通過(guò)一些特定參數,某些組件(如文本輸入組件)的當前設置可直接與應用程序的變量關(guān)聯(lián)。這些參數包括 variable 、 textvariable 、 onvalue 、 offvalue 、 value。這種關(guān)聯(lián)是雙向的:只要這些變量因任何原因發(fā)生變化,其關(guān)聯(lián)的部件就會(huì )更新以反映新的參數值。

不幸的是,在目前 tkinter 的實(shí)現代碼中,不可能通過(guò) variabletextvariable 參數將任意 Python 變量移交給組件。變量只有是 tkinter 中定義的 Variable 類(lèi)的子類(lèi),才能生效。

已經(jīng)定義了很多有用的 Variable 子類(lèi): StringVar 、 IntVar 、DoubleVarBooleanVar。調用 get() 方法可以讀取這些變量的當前值;調用 set() 方法則可改變變量值。只要遵循這種用法,組件就會(huì )保持跟蹤變量的值,而不需要更多的干預。

例如:

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 有個(gè)實(shí)用命令 wm,用于與窗口管理器進(jìn)行交互。wm 命令的參數可用于控制標題、位置、圖標之類(lèi)的東西。在 tkinter 中,這些命令已被實(shí)現為 Wm 類(lèi)的方法。頂層部件是 Wm 類(lèi)的子類(lèi),所以可以直接調用 Wm 的這些方法。

要獲得指定部件所在的頂層窗口,通常只要引用該部件的主窗口即可。當然,如果該部件是包裝在框架內的,那么主窗口不代表就是頂層窗口。為了獲得任意組件所在的頂層窗口,可以調用 _root() 方法。該方法以下劃線(xiàn)開(kāi)頭,表明其為 Python 實(shí)現的代碼,而非 Tk 提供的某個(gè)接口。

以下是一些典型用法:

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 參數的數據類(lèi)型?

anchor

合法值是羅盤(pán)的方位點(diǎn):"n" 、"ne" 、"e" 、"se" 、"s" 、"sw" 、"w" 、"nw""center" 。

bitmap

內置已命名的位圖有八個(gè):'error'、 'gray25' 、'gray50' 、'hourglass'、 'info' 、'questhead' 、'question' 、'warning' 。若要指定位圖的文件名,請給出完整路徑,前面加一個(gè) @,比如 "@/usr/contrib/bitmap/gumby.bit"。

boolean

可以傳入整數 0 或 1,或是字符串 "yes""no"。

callback -- 回調

指任何無(wú)需調用參數的 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 中的標準光標名稱(chēng),去掉 XC_ 前綴。 比如要獲取一個(gè)手形光標(XC_hand2),可以用字符串 "hand2"。也可以指定自己的位圖和掩碼文件作為光標。參見(jiàn) Ousterhout 書(shū)中的第 179 頁(yè)。

distance

屏幕距離可以用像素或絕對距離來(lái)指定。像素是數字,絕對距離是字符串,后面的字符表示單位:c 是厘米,i 是英寸,m 是毫米,p 則表示打印機的點(diǎn)數。例如,3.5 英寸可表示為 "3.5i"。

font

Tk 采用一串名稱(chēng)的格式表示字體,例如 {courier 10 bold}。正數的字體大小以點(diǎn)為單位,負數的大小以像素為單位。

geometry

這是一個(gè) widthxheight 形式的字符串,其中寬度和高度對于大多數部件來(lái)說(shuō)是以像素為單位的(對于顯示文本的部件來(lái)說(shuō)是以字符為單位的)。例如:fred["geometry"] = "200x100"。

justify

合法的值為字符串: "left" 、 "center" 、 "right""fill" 。

region

這是包含四個(gè)元素的字符串,以空格分隔,每個(gè)元素是表示一個(gè)合法的距離值(見(jiàn)上文)。例如:"2 3 4 5" 、 "3i 2i 4.5i 2i""3c 2c 4c 10.43c" 都是合法的區域值。

relief

決定了組件的邊框樣式。 合法值包括:"raised"、 "sunken" 、"flat" 、"groove""ridge" 。

scrollcommand

這幾乎就是帶滾動(dòng)條部件的 set() 方法,但也可是任一只有一個(gè)參數的部件方法。

wrap

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

綁定和事件?

部件命令中的 bind 方法可覺(jué)察某些事件,并在事件發(fā)生時(shí)觸發(fā)一個(gè)回調函數。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

是帶有一個(gè)參數的 Python 函數,發(fā)生事件時(shí)將會(huì )調用。傳入的參數為一個(gè) Event 實(shí)例。(以這種方式部署的函數通常稱(chēng)為 回調函數。)

add

可選項, '''+' 。傳入空字符串表示本次綁定將替換與此事件關(guān)聯(lián)的其他所有綁定。傳遞 '+' 則意味著(zhù)加入此事件類(lèi)型已綁定函數的列表中。

例如:

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

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

請注意,在 turn_red() 回調函數中如何訪(fǎng)問(wèn)事件的 widget 字段。該字段包含了捕獲 X 事件的控件。下表列出了事件可供訪(fǎng)問(wèn)的其他字段,及其在 Tk 中的表示方式,這在查看 Tk 手冊時(shí)很有用處。

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 函數可用于訪(fǎng)問(wèn)文本控件中的這些特定位置:

Text 控件的索引

Text 控件的索引語(yǔ)法非常復雜,最好還是在 Tk 手冊中查看。

Menu 索引(menu.invoke()、menu.entryconfig() 等)

菜單的某些屬性和方法可以操縱特定的菜單項。只要屬性或參數需要用到菜單索引,就可用以下方式傳入:

  • 一個(gè)整數,指的是菜單項的數字位置,從頂部開(kāi)始計數,從 0 開(kāi)始;

  • 字符串 "active",指的是當前光標所在的菜單;

  • 字符串 "last",指的是上一個(gè)菜單項;

  • 帶有 @ 前綴的整數,比如 @6,這里的整數解釋為菜單坐標系中的 y 像素坐標;

  • 表示沒(méi)有任何菜單條目的字符串 "none" 經(jīng)常與 menu.activate() 一同被用來(lái)停用所有條目,以及 ——

  • 與菜單項的文本標簽進(jìn)行模式匹配的文本串,從菜單頂部掃描到底部。請注意,此索引類(lèi)型是在其他所有索引類(lèi)型之后才會(huì )考慮的,這意味著(zhù)文本標簽為 last、activenone 的菜單項匹配成功后,可能會(huì )視為這些單詞文字本身。

圖片?

通過(guò) tkinter.Image 的各種子類(lèi)可以創(chuàng )建相應格式的圖片:

  • BitmapImage 對應 XBM 格式的圖片。

  • PhotoImage 對應 PGM、PPM、GIF 和 PNG 格式的圖片。后者自 Tk 8.6 開(kāi)始支持。

這兩種圖片可通過(guò) filedata 屬性創(chuàng )建的(也可能由其他屬性創(chuàng )建)。

然后可在某些支持 image 屬性的控件中(如標簽、按鈕、菜單)使用圖片對象。這時(shí),Tk 不會(huì )保留對圖片對象的引用。當圖片對象的最后一個(gè) Python 引用被刪除時(shí),圖片數據也會(huì )刪除,并且 Tk 會(huì )在用到圖片對象的地方顯示一個(gè)空白框。

參見(jiàn)

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

文件處理程序?

Tk 允許為文件操作注冊和注銷(xiāo)一個(gè)回調函數,當對文件描述符進(jìn)行 I/O 時(shí),Tk 的主循環(huán)會(huì )調用該回調函數。每個(gè)文件描述符只能注冊一個(gè)處理程序。示例代碼如下:

import tkinter
widget = tkinter.Tk()
mask = tkinter.READABLE | tkinter.WRITABLE
widget.tk.createfilehandler(file, mask, callback)
...
widget.tk.deletefilehandler(file)

在 Windows 系統中不可用。

由于不知道可讀取多少字節,你可能不希望使用 BufferedIOBaseTextIOBaseread()readline() 方法,因為這些方法必須讀取預定數量的字節。 對于套接字,可使用 recv()recvfrom() 方法;對于其他文件,可使用原始讀取方法或 os.read(file.fileno(), maxbytecount)。

Widget.tk.createfilehandler(file, mask, func)?

注冊文件處理程序的回調函數 func。 file 參數可以是具備 fileno() 方法的對象(例如文件或套接字對象),也可以是整數文件描述符。 mask 參數是下述三個(gè)常量的邏輯“或”組合?;卣{函數將用以下格式調用:

callback(file, mask)
Widget.tk.deletefilehandler(file)?

注銷(xiāo)文件處理函數。

tkinter.READABLE?
tkinter.WRITABLE?
tkinter.EXCEPTION?

Constants used in the mask arguments.