tkinter
--- Tcl/Tk 的 Python 介面¶
tkinter
套件(「Tk 介面」)是 Tcl/Tk GUI 工具集的標準 Python 介面。Tk 和 tkinter
在大多數 Unix 平台(包含 macOS)以及 Windows 系統上都可以使用。
從命令列執行 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)引入了一套現代化的主題式使用者介面元件,以及一個用以操作它們的新 API。新舊 API 目前都還能使用。你在網路上找到的大多數文件仍使用舊版 API,而且可能已經嚴重過時。
也參考
- TkDocs
關於使用 Tkinter 建立使用者介面的詳盡教學。內容解釋了關鍵概念,並使用現代 API 來說明建議的方法。
- Tkinter 8.5 reference: a GUI for Python
Tkinter 8.5 的參考文件,詳細說明了可用的類別、方法和選項。
Tcl/Tk 相關資源:
書籍:
- Modern Tkinter for Busy Python Developers
由 Mark Roseman 所著。(ISBN 978-1999149567)
- Python GUI programming with Tkinter
由 Alan D. Moore 所著。(ISBN 978-1788835886)
- Programming Python
由 Mark Lutz 所著;對 Tkinter 有極佳的涵蓋。(ISBN 978-0596158101)
- Tcl and the Tk Toolkit (2nd edition)
由 Tcl/Tk 發明者 John Ousterhout 與 Ken Jones 所著;不包含 Tkinter。(ISBN 978-0321336330)
架構¶
Tcl/Tk 並非單一函式庫,而是由幾個不同的模組所組成,每個模組都有獨立的功能和官方文件。Python 的二進位發行版也隨附了一個附加模組。
- Tcl
Tcl 是一個動態直譯的程式語言,就像 Python 一樣。雖然它可以作為通用程式語言獨立使用,但它最常被嵌入到 C 應用程式中,作為腳本引擎或 Tk 工具集的介面。Tcl 函式庫有一個 C 介面,可用於建立和管理一個或多個 Tcl 直譯器的實例,在這些實例中執行 Tcl 指令和腳本,並新增以 Tcl 或 C 實作的自訂指令。每個直譯器都有一個事件佇列,並有設施可以向其傳送事件並加以處理。與 Python 不同,Tcl 的執行模型是圍繞著協同多工(cooperative multitasking)設計的,而 Tkinter 則彌合了這種差異(詳情請參閱 Threading model)。
- Tk
Tk 是一個以 C 實作的 Tcl 套件,它新增了自訂指令來建立和操作 GUI 元件。每個
Tk
物件都嵌入了自己載入 Tk 的 Tcl 直譯器實例。Tk 的元件非常可自訂,但代價是外觀較為過時。Tk 使用 Tcl 的事件佇列來產生和處理 GUI 事件。- Ttk
主題式 Tk(Ttk)是較新的一族 Tk 元件,相較於許多傳統的 Tk 元件,它在不同平台上提供了更好的外觀。從 Tk 8.5 版開始,Ttk 作為 Tk 的一部分發行。Python 的繫結(bindings)則在一個獨立的模組
tkinter.ttk
中提供。
在內部,Tk 和 Ttk 使用底層作業系統的設施,即 Unix/X11 上的 Xlib、macOS 上的 Cocoa、Windows 上的 GDI。
當你的 Python 應用程式使用 Tkinter 中的類別(例如,建立一個元件)時,tkinter
模組會先組合一個 Tcl/Tk 指令字串。它將該 Tcl 指令字串傳遞給一個內部的 _tkinter
二進位模組,後者再呼叫 Tcl 直譯器來對其進行計算。Tcl 直譯器接著會呼叫 Tk 和/或 Ttk 套件,而這些套件又會再呼叫 Xlib、Cocoa 或 GDI。
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
。
- 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 取代時,將會被棄用。turtle
在 Tk 視窗中的海龜繪圖。
Tkinter 應急指南¶
本節並非旨在成為 Tk 或 Tkinter 的詳盡教學。為此,請參閱前面提到的外部資源之一。相反地,本節提供了一個快速導覽,介紹 Tkinter 應用程式的外觀、識別基礎的 Tk 概念,並解釋 Tkinter 包裝器的結構。
本節的其餘部分將幫助你識別在 Tkinter 應用程式中所需的類別、方法和選項,以及在哪裡可以找到關於它們的更詳細文件,包括在官方的 Tcl/Tk 參考手冊中。
一個 Hello World 程式¶
我們將從一個 Tkinter 的 "Hello World" 應用程式開始。這不是我們能寫出的最小程式,但足以說明一些你需要知道的關鍵概念。
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()
在引入之後,下一行建立了一個 Tk
類別的實例,它會初始化 Tk 並建立其關聯的 Tcl 直譯器。它還會建立一個頂層視窗,稱為根視窗,作為應用程式的主視窗。
接下來的一行建立了一個框架元件,在本例中,它將包含我們接下來要建立的一個標籤和一個按鈕。該框架被放置在根視窗內。
下一行建立了一個包含靜態文字字串的標籤元件。grid()
方法用於指定標籤在其包含的框架元件中的相對佈局(位置),類似於 HTML 中表格的運作方式。
然後建立一個按鈕元件,並放置在標籤的右側。當按下時,它將呼叫根視窗的 destroy()
方法。
最後,mainloop()
方法將所有內容顯示在螢幕上,並回應使用者輸入,直到程式終止。
重要的 Tk 概念¶
即使是這個簡單的程式也說明了以下關鍵的 Tk 概念:
- 元件(widgets)
一個 Tkinter 使用者介面是由個別的元件所組成。每個元件都表示為一個 Python 物件,從
ttk.Frame
、ttk.Label
和ttk.Button
等類別實例化而來。- 元件階層(widget hierarchy)
元件被安排在一個階層中。標籤和按鈕被包含在一個框架內,而框架又被包含在根視窗內。在建立每個子元件時,其父元件會作為第一個引數傳遞給元件的建構函式。
- 設定選項(configuration options)
元件具有設定選項,可以修改其外觀和行為,例如在標籤或按鈕中顯示的文字。不同類別的元件會有不同的選項集。
- 佈局管理(geometry management)
元件在建立時不會自動新增到使用者介面中。像
grid
這樣的佈局管理器(geometry manager)會控制它們在使用者介面中的放置位置。- 事件迴圈(event loop)
Tkinter 只有在主動執行事件迴圈時,才會對使用者輸入、程式的變更,甚至螢幕刷新做出反應。如果你的程式沒有執行事件迴圈,你的使用者介面將不會更新。
了解 Tkinter 如何包裝 Tcl/Tk¶
當你的應用程式使用 Tkinter 的類別和方法時,Tkinter 內部正在組合代表 Tcl/Tk 指令的字串,並在附加到你應用程式 Tk
實例的 Tcl 直譯器中執行這些指令。
無論是試圖瀏覽參考文件、尋找正確的方法或選項、改寫一些現有程式碼,還是偵錯你的 Tkinter 應用程式,在某些時候,了解那些底層 Tcl/Tk 指令的樣貌會很有幫助。
為了說明,以下是上面 Tkinter 腳本主要部分的 Tcl/Tk 對等程式碼。
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 的語法類似於許多 shell 語言,第一個字是要執行的指令,後面跟著該指令的引數,以空格分隔。在不深入太多細節的情況下,請注意以下幾點:
用於建立元件的指令(如
ttk::frame
)對應於 Tkinter 中的元件類別。Tcl 元件選項(如
-text
)對應於 Tkinter 中的關鍵字引數。在 Tcl 中,元件是透過路徑名稱(如
.frm.btn
)來參照,而 Tkinter 不使用名稱,而是使用物件參照。元件在元件階層中的位置被編碼在其(階層式)路徑名稱中,該路徑名稱使用
.
(點)作為路徑分隔符。根視窗的路徑名稱就是.
(點)。在 Tkinter 中,階層不是由路徑名稱定義的,而是在建立每個子元件時指定父元件來定義的。在 Tcl 中實作為獨立指令的操作(如
grid
或destroy
),在 Tkinter 中則表示為元件物件上的方法。正如你稍後會看到的,在其他時候,Tcl 使用的看起來像是對元件物件的方法呼叫,這更接近 Tkinter 中的用法。
我該如何...?哪個選項可以...?¶
如果你不確定如何在 Tkinter 中做某件事,並且無法立即在你正在使用的教學或參考文件中找到它,這裡有一些可能有幫助的策略。
首先,請記住,個別元件的運作細節可能會因 Tkinter 和 Tcl/Tk 的不同版本而異。如果你正在搜尋文件,請確保它對應於你系統上安裝的 Python 和 Tcl/Tk 版本。
在搜尋如何使用 API 時,知道你正在使用的類別、選項或方法的確切名稱會很有幫助。自省(Introspection),無論是在互動式 Python shell 中還是使用 print()
,都可以幫助你識別所需內容。
要找出任何元件上有哪些可用的設定選項,請呼叫其 configure()
方法,該方法會回傳一個字典,其中包含有關每個物件的各種資訊,包括其預設值和目前值。使用 keys()
僅取得每個選項的名稱。
btn = ttk.Button(frm, ...)
print(btn.configure().keys())
由於大多數元件有許多共通的設定選項,找出特定於某個元件類別的選項會很有用。將選項串列與像框架這樣較簡單的元件的選項串列進行比較,是做到這一點的一種方法。
print(set(btn.configure().keys()) - set(frm.configure().keys()))
同樣地,你可以使用標準的 dir()
函式來尋找元件物件可用的方法。如果你試一下,你會看到有超過 200 個常見的元件方法,所以再次強調,識別特定於某個元件類別的方法是很有幫助的。
print(dir(btn))
print(set(dir(btn)) - set(dir(frm)))
執行緒模型¶
Python 和 Tcl/Tk 有非常不同的執行緒模型,tkinter
試圖彌合這種差異。如果你使用執行緒,你可能需要意識到這一點。
一個 Python 直譯器可能有多個與之關聯的執行緒。在 Tcl 中,可以建立多個執行緒,但每個執行緒都有一個獨立的 Tcl 直譯器實例與之關聯。執行緒也可以建立多個直譯器實例,但每個直譯器實例只能由建立它的那個執行緒使用。
由 tkinter
建立的每個 Tk
物件都包含一個 Tcl 直譯器。它還會追蹤是哪個執行緒建立了該直譯器。可以從任何 Python 執行緒呼叫 tkinter
。在內部,如果呼叫來自建立 Tk
物件的執行緒以外的執行緒,則會將一個事件發佈到直譯器的事件佇列中,執行後,結果會回傳給呼叫的 Python 執行緒。
Tcl/Tk 應用程式通常是事件驅動的,這意味著在初始化之後,直譯器會執行一個事件迴圈(即 Tk.mainloop()
)並回應事件。因為它是單執行緒的,事件處理常式必須快速回應,否則它們會阻塞其他事件的處理。為避免這種情況,任何長時間執行的計算都不應在事件處理常式中執行,而是使用計時器將其分解成更小的部分,或在另一個執行緒中執行。這與許多 GUI 工具集不同,在那些工具集中,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 pages。
請注意,man pages 為每個元件列出了「標準選項」和「元件特定選項」。前者是許多元件共有的選項串列,後者是該特定元件特有的選項。標準選項記錄在 options(3) man page 中。
本文件中未對標準選項和元件特定選項進行區分。某些選項不適用於某些類型的元件。給定元件是否回應特定選項取決於該元件的類別;按鈕有 command
選項,標籤則沒有。
給定元件支援的選項列在該元件的 man page 中,或者可以在 runtime 透過不帶引數呼叫 config()
方法,或對該元件呼叫 keys()
方法來查詢。這些呼叫的回傳值是一個字典,其鍵是選項名稱的字串(例如 'relief'
),其值是 5-tuples。
某些選項,如 bg
,是具有長名稱的常見選項的同義詞(bg
是 "background" 的簡寫)。將簡寫選項的名稱傳遞給 config()
方法將回傳一個 2-tuple,而不是 5-tuple。回傳的 2-tuple 將包含同義詞的名稱和「真實」選項(例如 ('bg', 'background')
)。
索引 |
含義 |
範例 |
---|---|---|
0 |
選項名稱 |
|
1 |
用於資料庫查詢的選項名稱 |
|
2 |
用於資料庫查詢的選項類別 |
|
3 |
預設值 |
|
4 |
目前值 |
|
範例:
>>> print(fred.config())
{'relief': ('relief', 'relief', 'Relief', 'raised', 'groove')}
當然,印出的字典將包含所有可用的選項及其值。這僅作為一個範例。
Packer 佈局管理器¶
packer 是 Tk 的佈局管理(geometry manager)機制之一。佈局管理器(geometry manager)用於指定元件在其容器(它們共同的 master)內的相對位置。與較為繁瑣的 placer(較不常用,我們在此不予介紹)相比,packer 採用定性的關係規範——上方、左方、填滿等——並為你計算出確切的放置座標。
任何 master 元件的大小由其內部的「slave 元件」的大小決定。packer 用於控制 slave 元件在被 packed 的 master 內部出現的位置。你可以將元件 pack 到框架中,再將框架 pack 到其他框架中,以達到你想要的佈局。此外,一旦 packed,佈局會動態調整以適應設定的增量變更。
請注意,元件在透過佈局管理器(geometry manager)指定其佈局(geometry)之前是不會出現的。一個常見的早期錯誤是忽略了佈局(geometry)指定,然後在元件被建立但沒有任何東西出現時感到驚訝。一個元件只有在例如 packer 的 pack()
方法被應用於其上之後才會出現。
pack() 方法可以與關鍵字選項/值對一起呼叫,以控制元件在其容器中出現的位置,以及當主應用程式視窗調整大小時它的行為方式。以下是一些範例:
fred.pack() # 預設為 side = "top"
fred.pack(side="left")
fred.pack(expand=1)
Packer 選項¶
有關 packer 及其可接受選項的更詳盡資訊,請參閱 man pages 和 John Ousterhout 書中的第 183 頁。
- anchor
錨點類型。表示 packer 將每個 slave 放置在其區域中的位置。
- expand
布林值,
0
或1
。- fill
合法值:
'x'
、'y'
、'both'
、'none'
。- ipadx 和 ipady
一個距離——指定 slave 元件每側的內部填充。
- padx 和 pady
一個距離——指定 slave 元件每側的外部填充。
- 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()
# 建立應用程式變數。
self.contents = tk.StringVar()
# 將其設定為某個值。
self.contents.set("this is a variable")
# 告訴 entry 元件監視此變數。
self.entrythingy["textvariable"] = self.contents
# 為使用者按下 return 鍵定義一個回呼。
# 它會印出變數的目前值。
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
方法。
要取得包含給定元件的頂層視窗,你通常可以直接參照該元件的 master。當然,如果該元件被 packed 在一個框架內,master 將不代表一個頂層視窗。要取得包含任意元件的頂層視窗,你可以呼叫 _root()
方法。此方法以底線開頭,表示此函式是實作的一部分,而不是 Tk 功能的介面。
以下是一些常見用法範例:
import tkinter as tk
class App(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
# 建立應用程式
myapp = App()
#
# 以下是對視窗管理器類別的方法呼叫
#
myapp.master.title("My Do-Nothing Application")
myapp.master.maxsize(1000, 400)
# 啟動程式
myapp.mainloop()
Tk 選項資料型別¶
- anchor
合法值為羅盤方位點:
"n"
、"ne"
、"e"
、"se"
、"s"
、"sw"
、"w"
、"nw"
,以及"center"
。- bitmap
有八個內建的、命名的點陣圖:
'error'
、'gray25'
、'gray50'
、'hourglass'
、'info'
、'questhead'
、'question'
、'warning'
。要指定一個 X 點陣圖檔名,請給出檔案的完整路徑,並在前面加上一個@
,例如"@/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 檔案中的 X 顏色名稱給出,或以表示 RGB 值的字串給出,範圍可以是 4 位元:
"#RGB"
、8 位元:"#RRGGBB"
、12 位元:"#RRRGGGBBB"
或 16 位元:"#RRRRGGGGBBBB"
,其中 R、G、B 在此代表任何合法的十六進位數字。詳情請參閱 Ousterhout 書中的第 160 頁。- cursor
可以使用
cursorfont.h
中的標準 X 游標名稱,無需XC_
前綴。例如,要取得手形游標(XC_hand2
),請使用字串"hand2"
。你也可以指定自己的點陣圖和遮罩檔案。請參閱 Ousterhout 書中的第 179 頁。- distance
螢幕距離可以以像素或絕對距離指定。像素以數字給出,絕對距離以字串給出,尾隨字元表示單位:
c
代表公分,i
代表英寸,m
代表毫米,p
代表印刷的點。例如,3.5 英寸表示為"3.5i"
。- font
Tk 使用串列字型名稱格式,例如
{courier 10 bold}
。帶有正數的字型大小以點為單位;帶有負數的大小以像素為單位。- geometry
這是一個
widthxheight
形式的字串,其中 width 和 height 對於大多數元件是以像素為單位(對於顯示文字的元件則以字元為單位)。例如: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
是一個表示目標事件類型的字串。(詳情請參閱 bind(3tk) man page,以及 John Ousterhout 的書 Tcl and the Tk Toolkit (2nd edition) 的第 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 man pages 時可能很有用。
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 man pages 中有最好的描述。
- 選單索引(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
選項建立的(也有其他選項可用)。
在 3.13 版的變更: 新增了 PhotoImage
方法 copy_replace()
,用於將一個區域從一個圖片複製到另一個圖片,可能帶有像素縮放和/或子採樣。將 from_coords 參數新增到 PhotoImage
方法 copy()
、zoom()
和 subsample()
。將 zoom 和 subsample 參數新增到 PhotoImage
方法 copy()
。
然後,圖片物件可以在任何支援 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()
方法,因為這些方法會堅持讀取預定義數量的位元組。對於 sockets(通訊端),recv()
或 recvfrom()
方法可以正常運作;對於其他檔案,請使用原始讀取或 os.read(file.fileno(), maxbytecount)
。
- Widget.tk.createfilehandler(file, mask, func)¶
註冊檔案處理常式回呼函式 func。file 引數可以是一個具有
fileno()
方法的物件(例如檔案或 socket(通訊端)物件),或是一個整數檔案描述器。mask 引數是下面三個常數中任意一個的 OR 組合。回呼函式被呼叫的方式如下:callback(file, mask)
- Widget.tk.deletefilehandler(file)¶
取消註冊檔案處理常式。