【python第十周】Tkinter基本入門文字教程


什么是Tkinter


Tkinter(也叫Tk接口)是Tk圖形用戶界面工具包標准的Python接口。Tk是一個輕量級的跨平台圖形用戶界面(GUI)開發工具。TkTkinter可以運行在大多數的Unix平台、Windows、和Macintosh系統。
Tkinter 由一定數量的模塊組成。Tkinter位於一個名為_tkinter(較早的版本名為tkinter)的二進制模塊中 。Tkinter包含了對Tk的低 級接口模塊,低級接口並不會被應用級程序員直接使用,通常是一個共享庫(或DLL),但是在一些情況下它也被Python解釋器靜態鏈接。
除了Tk接口模塊,Tkinter也包含了一定數量的Python模塊。其中兩個最重要的模塊是Tkinter本身和名為Tkconstants的模塊。前者自動引導后者,因此使用Tkinter,你首先需要做的是導入Tkinter模塊,
代碼如下:
import Tkinter

from Tkinter import *

 

 

 

第一個Tkinter程序



一、代碼如下:
# File: hello1.py

from Tkinter import *

root = Tk()

w = Label(root, text="Hello, world!")
w.pack()

root.mainloop()
運行結果如下:

關閉這個窗口即可終止這個程序的運行。

二、對代碼的說明:

我們通過導入Tkinter模塊開始。Tkinter模塊包含了用Tk工具包工作所需的所有的類,函數和其它一些必須的東西。在大多數情況下,你只需要簡單的從Tkinter導入所有的東西到你的模塊的名字空間,如下所示:
from Tkinter import *

后初始化Tkinter,方法是我們必須先創建一個Tk root(根)窗口部件,它是一個普通的窗口,帶有標題條和其它由你的窗口管理器供給的附屬。你 應該只創建一個root窗口部件,這個root窗口部件必須在其它窗口部件創建之前創建。初始化Tkinter的代碼如下:
root = Tk()

接着我們創建一個Label(標簽)窗口部件作為這個root窗口的孩子,代碼如下:
w = Label(root, text=" http://www.bboby.com !")
Label窗口部件可以顯示文本、圖標或圖象。我們這里用text選項來指定要顯示的文本。

接下來我們在Label窗口部件上調用了pack方法,它告訴Label窗口部件去調整自己的尺寸來適應所給定文本的大小,並且使用自己可見,代碼如下:
w.pack()

但是在這些發生之前,我們必須進入Tkinter的事件循環,代碼如下:
root.mainloop()

個程序將一直處在事件循環之中,直到我們關閉了這個窗口。事件循環不僅僅處理來自用戶的事件(如鼠標敲擊和按鍵按下)或者窗口系統(重繪事件和窗口配置消 息),它也處理來自Tkinter自身的工作等待隊列,這些工作之一就包括由pack方法所產生的工作和顯示更新。這就意味着這個應用程序窗口在進入這個 事件循環之前將不會顯示出來。
 

 

第二個Tkinter程序



當我們在寫一個較大的程序的時候,把代碼封裝在類中通常是一個好的主意。

一、代碼如下:

# File: hello2.py

from Tkinter import *

class App:

    def __init__(self, master):

        frame = Frame(master)
        frame.pack()

        self.button = Button(frame, text="QUIT", fg="red", command=frame.quit)
        self.button.pack(side= http://www.bboby.com  LEFT)

        self.hi_there = Button(frame, text="Hello", command=self.say_hi)
        self.hi_there.pack(side=LEFT)

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

root = Tk()

app = App(root)

root.mainloop()
運行結果如下:

 

 


如果你點擊Hello按鈕,將在控制台打印出"hi there, everyone!" 。如果你點擊QUIT按鈕,程序將終止。

二、代碼說明:

這個簡單的應用程序被寫成了一個類。這個構造器(__init__ 方法)通過一個父部件被調用,並針對父部件增加了一些子部件。構造器通過創建一個Frame(幀)窗口部件開始。一個幀是一個簡單的容器,在這個例子中,我們僅用來容納另外的兩個部件。
class App:
        def __init__(self, master):

            frame = Frame(master)
            frame.pack()
這個幀實例被存儲在一個名為Frame的局部變量中。在創建了這個部件后,我們立即調用pack方法來使用這個幀可見。

然后我們創建兩個Button(按鈕)窗口部件作為這個幀的孩子。
self.button = Button(frame, text="QUIT", fg="red", command=frame.quit)
self.button.pack(side=LEFT)

self.hi_there = Button(frame, text="Hello", command=self.say_hi)
self.hi_there.pack(side=LEFT)
這次,我們傳遞了一定數量的選項給構造器。第一個按鈕被標為"QUIT",字為紅色(fgforeground<前景色>的縮寫)。第二個被標為"Hello"。兩個按鈕都有一個command選項。這個選項指定了一個函數或方法,在按鈕被點擊時會被調用。

按鈕實例被存儲在實例屬性組中。side=LEFT 參數表示這兩個按鈕在幀中將被分開放置;第一個按鈕被放置在幀的左邊緣,第二個被放在第一個的右邊(幀 的左邊緣仍保留着空格)。默認情況下,部件的放置都是相對於它們的父親(frame部件相對於masterbutton相對於frame)。如果 side選項沒指定,side默認值為TOP

"Hello"按鈕的回調函數如下所示,它在按鈕每次被按下時簡單地打印一條信息給控制台:
def say_hi(self):
        print "hi there, everyone!"

最后我們提供了一些腳本級的代碼來創建一個Tk root部件,和一個App類的實例(這個實例使用這個root部件作為它的父親):
root = Tk()

app = App(root)

root.mainloop()

root.mainloop()調用root部件的mainloop方法。它進入Tk事件循環,這個應用程序將處於這個Tk事件循環之中直到quit方法被調用(點擊QUIT按鈕),或窗口被關閉。

 關於窗口部件引用



在第二個例子中,frame部件被存儲在一個名為frame的局部變量中,而button部件則存儲在兩個實例的屬性組中。這是否隱藏着一個嚴重的問題呢:當 __init__ 函數返回並且frame變量超出了范圍會發生什么呢?。

要緊;這兒確實沒有必要去保持對窗口部件實例的引用。Tkinter自動維護一個窗口部件樹(通過對象實例的masterchildren屬性),因 此,當應用程序的最后一個引用消失時窗口部件不會消失;窗口部件必須顯的用destroy方法銷毀。但是如果你希望在窗口部件被創建以后用它來做一些事情,你最好保持對你自己的窗口部件實例的引用。

注意如果你不需要保持對一個窗口部件的引用,你可以用單獨的一行來創建和pack(包裝)它,如下:
Button(frame, text="Hello", command=self.hello).pack(side=LEFT)

不要存儲這個操作的結果,當你試圖去用這個結果時你會很失望(因為pack方法返回None)。為小心起見,最好將將pack(包裝)分開,如下所示:
w = Button(frame, text="Hello", command=self.hello)
w.pack(side=LEFT)

 
關於窗口部件的名字
另一個容引起混淆的方面(尤其是使用Tcl編程Tk的有一些經驗的人)是Tkinter的窗口部件的名字的概念。在Tcl中,你必須顯的命名每一個窗口部件。例如下面的Tcl命令創建一個名為ok的按鈕作為名為dialog的窗口部件的孩子(dialog又是root窗口的孩子):
button .dialog.ok

相應的Tkinter調用將如下:
ok = Button(dialog)
在這個Tkinter案例中,okdialog是對窗口部件實例的引用,不是窗口部件實際的名字。因為Tk自身需要這些名字,Tkinter自動為每個新 窗口部件賦一個唯一的名字。在這個Tkinter案例中,這個dialog的名字或許類似".1428748",並且button可能 是".1428748.1432920"。如果你希望得到一個Tkinter窗口部件的完整名字,你可以在這個窗口部件實例上使用str函數:
>>> print str(ok)
.1428748.1432920

如果你確實需要為一個窗口部件指定一個名字,你可以在你創建這個窗口部件時使用name選項。你這么做的原因可能是你需要和用Tcl寫的代碼接口。

下面的例子將產生一個名為".dialog.ok"的窗口部件(如果你忘了命名dialog,那么名字可能類似".1428748.ok"):
ok = Button(dialog, name="ok")

為了避免與此同時Tkinter的名字機制相沖突,不要使用只包含數字的名字。同樣注意name是只能創建一次的選項;一旦你創建了這個部件的名字,那么你就不能再改變它的名字了。
 
Tkinter類之窗口部件類
Tkinter支持15個核心的窗口部件,這個15個核心窗口部件類列表如下:

窗口部件及說明:

Button
一個簡單的按鈕,用來執行一個命令或別的操作。

Canvas
組織圖形。這個部件可以用來繪制圖表和圖,創建圖形編輯器,實現定制窗口部件。

Checkbutton
代表一個變量,它有兩個不同的值。點擊這個按鈕將會在這兩個值間切換。

Entry
文本輸入域。

Frame
一個容器窗口部件。幀可以有邊框和背景,當創建一個應用程序或dialog(對話)版面時,幀被用來組織其它的窗口部件。

Label
顯示一個文本或圖象。

Listbox
顯示供選方案的一個列表。listbox能夠被配置來得到radiobuttonchecklist的行為。

Menu
菜單條。用來實現下拉和彈出式菜單。

Menubutton
菜單按鈕。用來實現下拉式菜單。

Message
顯示一文本。類似label窗口部件,但是能夠自動地調整文本到給定的寬度或比率。

Radiobutton
代表一個變量,它可以有多個值中的一個。點擊它將為這個變量設置值,並且清除與這同一變量相關的其它radiobutton

Scale
允許你通過滑塊來設置一數字值。

Scrollbar
為配合使用canvas, entry, listbox, and text窗口部件的標准滾動條。

Text
格式化文本顯示。允許你用不同的樣式和屬性來顯示和編輯文本。同時支持內嵌圖象和窗口。

Toplevel
一個容器窗口部件,作為一個單獨的、最上面的窗口顯示。

注意在Tkinter中窗口部件類沒有分級;所有的窗口部件類在樹中都是兄弟。

所有這些窗口部件提供了Misc和幾何管理方法、配置管理方法和部件自己定義的另外的方法。此外,Toplevel類也提供窗口管理接口。這意味一個典型的窗口部件類提供了大約150種方法。
 

Button窗口部件



Button(按鈕)窗口部件是一個標准的Tkinter窗口部件,用來實現各種按鈕。按鈕能夠包含文本或圖象,並且你能夠將按鈕與一個Python函數或方法相關聯。當這個按鈕被按下時,Tkinter自動調用相關聯的函數或方法。

按鈕僅能顯示一種字體,但是這個文本可以跨行。另外,這個文本中的一個字母可以有下划線,例如標明一個快捷鍵。默認情況,Tab鍵用於將焦點移動到一個按鈕部件。

一、那么什么時候用按鈕部件呢?

簡而言之,按鈕部件用來讓用戶說馬上給我執行這個任務,通常我們用顯示在按鈕上的文本或圖象來提示。按鈕通常用在工具條中或應用程序窗口中,並且用來接收或忽略輸入在對話框中的數據。

關於按鈕和輸入的數據的配合,可以參看CheckbuttonRadiobutton部件。

二、樣式

普通的按鈕很容易被創建,僅僅指定按鈕的內容(文本、位圖、圖象)和一個當按鈕被按下時的回調函數即可:
b = Button(master, text="OK", command=self.ok)

沒有回調函數的按鈕是沒有用的,當你按下這個按鈕時它什么也不做。你可能在開發一個應用程序的時候想實現這種按鈕,比如為了不干擾你的beta版的測試者:
b = Button(master, text="Help", state=DISABLED)

如果你沒有指定尺寸,按鈕的大小將正好能夠容納它的內容。你可以用padxpady選項來增加內容與按鈕邊框的間距。你也可以用heightwidth 選項來顯式地設置按鈕的尺寸。如果你在按鈕中顯示文本,那么這些選項將以文本的單位為定義按鈕的尺寸。如果你替而代之顯示圖象,那么按鈕的尺寸將是象素 (或其它的屏幕單位)。你實際上甚至能夠用象素單位來定義文本按鈕的尺寸,但這可能帶來意外的結果。下面是指定尺寸的一段例子代碼:
f = Frame(master, height=32, width=32)
f.pack_propagate( http://www.bboby.com ) # don't shrink
b = Button(f, text="Sure!")
b.pack(fill=BOTH, expand=1)

按鈕能夠顯示多行文本(但只能用一種字體)。 你可以使用多行或wraplength選項來使按鈕自己調整文本。當調整文本時,使用anchor,justify,也可加上padx選項來得到你所希望的格式。一個例子如下:
b = Button(master, text=longtext, anchor=W, justify=LEFT, padx=2)

為了使一個普通的按鈕看起來像凹入的,例如你想去實現某種類型的工具框,你可簡單地將relief的值從"RAISED"改變為"SUNKEN
b.config(relief=SUNKEN)

你也可能想改變背景。注意:一個大概更好的解決方案是使用一個CheckbuttonRadiobuttonindicatoron選項的值設置為false
b = Checkbutton(master, image=bold, variable=var, indicatoron=0)

三、方法

Button窗口部件支持標准的Tkinter窗口部件接口,加上下面的方法:

flash()頻繁重畫按鈕,使其在活動和普通樣式下切換。

invoke() 調用與按鈕相關聯的命令。

下面的方法與你實現自己的按鈕綁定有關:

tkButtonDown(), tkButtonEnter(), tkButtonInvoke(), tkButtonLeave(), tkButtonUp()
這些方法可以用在定制事件綁定中,所有這些方法接收0個或多個形參。

四、選項

Button窗口部件支持下面的選項:

activebackground, activeforeground
類型:顏色;
說明:當按鈕被激活時所使用的顏色。

anchor
類型:常量;
說明:控制按鈕上內容的位置。使用N, NE, E, SE, S, SW, W, NW, or CENTER這些值之一。默認值是CENTER

background (bg), foreground (fg)
類型:顏色;
說明:按鈕的顏色。默認值與特定平台相關。

 

 


bitmap
類型:位圖;
明:顯示在窗口部件中的位圖。如果image選項被指定了,則這個選項被忽略。下面的位圖在所有平台上都有 效:error, gray75, gray50, gray25, gray12, hourglass, info, questhead, question, warning.

后面附加的位圖僅在Macintosh上有 效:document, stationery, edition, application, accessory, folder, pfolder, trash, floppy, ramdisk, cdrom, preferences, querydoc, stop, note, caution.

你也可以從一個XBM文件中裝載位圖。只需要在XBM文件名前加一個前綴@,例如"@sample.xbm"

borderwidth (bd)
類型:整數;
說明:按鈕邊框的寬度。默認值與特定平台相關。但通常是12象素。

command
類型:回調;
說明:當按鈕被按下時所調用的一個函數或方法。所回調的可以是一個函數、方法或別的可調用的Python對象。

cursor
類型:光標;
說明:當鼠標移動到按鈕上時所顯示的光標。

default
類型:常量;
說明:如果設置了,則按鈕為默認按鈕。注意這個語法在Tk 8.0b2中已改變。

disabledforeground
類型:顏色;
說明:當按鈕無效時的顏色。

font
類型:字體;
說明:按鈕所使用的字體。按鈕只能包含一種字體的文本。

highlightbackground, highlightcolor
類型:顏色;
說明:控制焦點所在的高亮邊框的顏色。當窗口部件獲得焦點的時候,邊框為highlightcolor所指定的顏色。否則邊框為highlightbackground所指定的顏色。默認值由系統所定。

highlightthickness
類型:距離;
說明:控制焦點所在的高亮邊框的寬度。默認值通常是12象素。

image
類型:圖象;
說明:在部件中顯示的圖象。如果指定,則textbitmap選項將被忽略。

justify
類型:常量;
說明:定義多行文本如何對齊。可取值有:LEFT, RIGHT, CENTER

padx, pady
類型:距離;
說明:指定文本或圖象與按鈕邊框的間距。

relief
類型:常量;
說明:邊框的裝飾。通常按鈕按下時是凹陷的,否則凸起。另外的可能取值有GROOVE, RIDGE, FLAT

state
類型:常量;
說明:按鈕的狀態:NORMAL, ACTIVE DISABLED。默認值為NORMAL

takefocus
類型:標志;
說明:表明用戶可以Tab鍵來將焦點移到這個按鈕上。默認值是一個空字符串,意思是如果按鈕有按鍵綁定的話,它可以通過所綁定的按鍵來獲得焦點。

text
類型:字符串;
說明:顯示在按鈕中的文本。文本可以是多行。如果bitmapsimage選項被使用,則text選項被忽略。

textvariable
類型:變量;
說明:與按鈕相關的Tk變量(通常是一個字符串變量)。如果這個變量的值改變,那么按鈕上的文本相應更新。

underline
類型:整數;
說明:在文本標簽中哪個字符加下划線。默認值為-1,意思是沒有字符加下划線。

width, height
類型:距離;
說明:按鈕的尺寸。如果按鈕顯示文本,尺寸使用文本的單位。如果按鈕顯示圖象,尺寸以象素為單位(或屏幕的單位)。如果尺寸沒指定,它將根據按鈕的內容來計算。

wraplength
類型:距離;
說明:確定一個按鈕的文本何時調整為多行。它以屏幕的單位為單位。默認不調整。

Mixins



Tkinter模塊提供了相應於Tk中的各種窗口部件類型的類和一定數量的mixin和別的幫助類(mixin是一個類,被設計來使用多態繼承與其它的類結合)。當你使用Tkinter時,你不將直接訪問mixin類。

一、實施mixins

通過root窗口和窗口部件類,Misc類被用作mixin。它提供了大量的Tk和窗口相關服務,這些服務對所有Tkinter核心窗口部件者有效。這些通過委托完成;窗口部件僅僅直接請求適當的內部對象。

Wm類通過root窗口和頂級窗口部件類被用作mixin。通過委托它提供了窗口管理服務。

使用委托像這樣簡化你的應用程序代碼:一旦你有一窗口部件,你能夠使用這個窗口部件的實例的方法訪問Tkinter的所有部份。

二、Geometry(幾何學)mixins

Grid,Pack,Place這些類通過窗口部件類被用作mixins。通過委托,它們也提供了訪問不同幾何管理的支持。
下面是Geometry Mixins的列表及說明:
管理器及說明:

Gridgrid幾何管理器允許你通過在一個二維網格中組織窗口部件來創建一個類似表的版面。
Packpack幾何管理器通過在一個幀中把窗口部件包裝到一個父部件中來創建一個版面。為了對窗口部件使用這個幾何管理器,我們在這個窗口部件上使用pack方法來集成。
Placeplace幾何管理器讓你顯式將一個窗口部件放到給定的位置。要使用這個幾何管理器,需使用place方法。

三、窗口部件配置管理
Widget類使用 geometry mixins來混合Misc類,並通過cgetconfigure方法來增加配置管理,也可以通過一個局部的字典接口。

 窗口部件的配置



要配置一個窗口部件的外觀,你用選項比使用方法調用好。典型的選項包括textcolorsizecommand等等。對於處理選項,所有的核心窗口部件執行同樣的配置接口:

配置接口

widgetclass(master, option=value, ...) => widget
說明:
建這個窗口部件的一個實例,這個實例作為給定的master的孩子,並且使用給定的選項。所有的選項都有默認值,因此在簡單的情況下,你僅需要指定這個 master。如果你想的話,你也可以不指定masterTkinter這時會使用最近創建的root窗口作為master。注意這個name選項僅能 在窗口部件被創建時設置。

cget(option) => string
說明:
返回一個選項的當前值。選項的名字和返回值都是字符串。要得到name選項,使用str(widget)代替。

configure(option=value, ...), config(option=value, ...)
說明:
設置一個或多個選項(作為關鍵字參數給定)。
注意一些選項的名字與Python中的保留字相同(class,from)。要使用這些作為關鍵字參數,僅需要在這些選項名后添加一下划線(class_,from_)。注意你不能用此方法來設置name選項;name選項只能在窗口部件被創建時設置。

為了方便起見,窗口部件也實現一個局部的字典接口。 __setitem__ 方法映射configure,而__getitem__方法映射cget。你可以使用下面的語法來設置和查詢選項:
value = widget[ http://www.bboby.com ]
widget[option] = value
注意每個賦值都導致一個對Tk的調用。如果你希望去改變多個選項,單獨地調用(configconfigure)去改變它們是一個好的主意。

這下面的字典方法也適用於窗口部件:
keys() => list
說明:
返回窗口部件中所有可以被設置的選項的一個列表。name選項不包括在這個列表中(它不能通過字典接口被查詢或修改)。

 

 向后兼容性



關鍵字參數在Python1.3時被引入。之前,使用原始的Python字典將選項傳遞給窗口構造器和configure方法。原代碼類似如下:
self.button = Button(frame, {"text": "QUIT", "fg": "red", "command": frame.quit})
self.button.pack({"side": LEFT})

關鍵字參數語法更優雅和少容易發生錯誤。但是為了與存在的代碼兼容,Tkinter仍支持老的語法。在新的程序中你不應再用老的語法,即使是在某些情況下是很有吸引力的。例如,如果你創建了一個定制的窗口部件,它需要沿它的父類傳遞配置選項,你的代碼可能如下:
def __init__(self, master, **kw):
    Canvas.__init__(self, master, kw) # kw 是一個字典
上面的代碼在當前版本的Tkinter下工作的很好,但是它在將來的版本下可能不工作。一個通常的辦法是使用apply函數:
def __init__(self, master, **kw):
    apply(Canvas.__init__, (self, master), kw)
這個apply函數使用了一個函數(一個未約束的方法),一個帶參數的元組(它必須包括self,因為我們調用一個未約束的方法),一個可選的,提供了關鍵字參數的字典。



 

 窗口部件的樣式之顏色



所有的Tkinter標准窗口部件提供了一套樣式設置選項,這讓你可以去修改這些窗口部件的外觀如顏色、字體和其它的可視外觀。

顏色

大部份窗口部件都允許你指定窗口部件和文本的顏色,這可以使用backgroundforeground選項。要指定顏色,你可以使用顏色名,也可以使用紅、綠、藍顏色組合。

1、顏色名
Tkinter 包括一個顏色數據庫,它將顏色名映射到相應的RGB值。這個數據庫包括了通常的名稱如Red, Green, Blue, Yellow, LightBlue,也可使用外來的如MoccasinPeachPuff等等。在X window系統上,顏色名由X server定義。你能夠找到 一個名為xrgb.txt的文件,它包含了一個由顏色名和相應RGB值組成的列表。在WindowsMacintosh系統上,顏色名表內建於Tk中。

Windows下,你可以使用Windows系統顏色(用戶可以通過控制面板來改變這些顏色):
SystemActiveBorder, SystemActiveCaption, SystemAppWorkspace, SystemBackground,
SystemButtonFace, SystemButtonHighlight, SystemButtonShadow, SystemButtonText,
SystemCaptionText, SystemDisabledText, SystemHighlight, SystemHighlightText,
SystemInactiveBorder, SystemInactiveCaption, SystemInactiveCaptionText, SystemMenu,
SystemMenuText, SystemScrollbar, SystemWindow, SystemWindowFrame, SystemWindowText

Macintosh上,下面的系統顏色是有效的:
SystemButtonFace, SystemButtonFrame, SystemButtonText, SystemHighlight, SystemHighlightText, SystemMenu, SystemMenuActive, SystemMenuActiveText, SystemMenuDisabled, SystemMenuText, SystemWindowBody

顏色名是大小寫不敏感的。許多顏色名詞與詞之間有無格都有效。例如"lightblue", "light blue",
"Light Blue"都是同一顏色。

2RGB格式

如果你需要顯式地指定顏色名,你可以使用如下格式的字符串:
#RRGGBB
RR, GG, BB 分別是red,greenblue值的十六進制表示。下面的例子演示了如何將一個顏色三元組轉換為

一個Tk顏色格式:
tk_rgb = "#%02x%02x%02x" % (128, 192, 200)

Tk也支持用形如"#RGB""rrrrggggbbbb"去分別指定1665536程度之間的值。

你可以使用窗口部件的winfo_rgb方法來將一個代表顏色的字符串(名字或RGB格式)轉換為一個三元組:
rgb = widget.winfo_rgb("red")
red, green, blue = rgb[0]/256, rgb[1]/256, rgb[2]/256
注意winfo_rgb返回16位的RGB值,范圍在0~65535之間。要將它們映射到更通用的0~255范圍內,你必須將每個值都除以256(或將它們向右移8位)。

 窗口部件的樣式之字體



字體
窗口部件允許你顯示文本和指定所使用的字體。所有的窗口部件都提供了合理的默認值,你很少需要去為簡單元素如標簽和按鈕指定字體。

字體通常使用font窗口部件選項指定。Tkinter支持一定數量的不同字體描述類型:
* Font descriptors

* User-defined font names

* System fonts

* X font descriptors

Tk8.0以前的版本僅X font描述被支持。

1、字體描述
Tk8.0開始,Tkinter支持獨立於平台的字體描述。你可以使用元組來指定一個字體,這個元組包含了一個字體類型名字,一個以磅為單位的高度,代表一個或多個樣式的字符串。例如:
("Times", 10, "bold")
("Helvetica", 10, "bold italic")
("Symbol", 8)

要得到默認的尺寸和類型,你可以給夢芭莎優惠券出作為單一字符串的字體名。如果這個字體類型名字沒有包括空格,你也可以給這個字符串自身增加尺寸和樣式:
"Times 10 bold"
"Helvetica 10 bold italic"
"Symbol 8"

在大部份Windows平台上存在如下有效的字體類名:
Arial (相 應 於 Helvetica), Courier New (Courier), Comic Sans MS, Fixedsys, MS Sans Serif, MS Serif, Symbol, System, Times New Roman (Times), Verdana

 

 


注意:如果這個字體類型名包含空格,你必須使用上面所描述的元組語法。

有效的樣式有normal, bold, roman, italic, underline, and overstrike

Tk8.0自動映射Courier, Helvetica, Times到所有平台上相應的本地字體類型名。此外,在Tk8.0下字體格式不會引起問題,如果Tk不能找出確切的匹配,它會試着找類似的字體,如果失敗,Tk就使用特定平台的默認字體。

Tk4.2Windows下同樣支持這種字體描述。這兒有幾個限制,包括字體類型名必須在平台上存在,並非這所有上面樣式名都存在(或它們中的一些有不同的名字)。

2、字體名
此外,Tk8.0允許你去創建已命名的字體並且當為一個窗口部件指定字體時使用它們的名字。

tkFont模塊提供一個Font類,這個類允許你去創建字體實例。你可以隨處使用這樣一個實例。你也可能使用一個字體實例來得到字體的量度,包括存在於那個字體中的字符串所站用的尺寸。

 tkFont.Font(family="Times", size=10, weight=tkFont.BOLD)
 tkFont.Font(family="Helvetica", size=10, weight=tkFont.BOLD,
             slant=tkFont.ITALIC)
 tkFont.Font(family="Symbol", size=8)

如果你修改一個已命名的字體(使用config方法),這個改變將自動影響到所有使用這個字體的窗口部件。

Font構造器支持下列的樣式選項(注意常量被定義在tkFont模塊中):

樣式選項及說明:

family選項
類型:字符串
說明:字體類型

size選項
類型:整型
說明:以磅為單位的字體的尺寸。要以象素為單位的話,使用負值。

weight選項
類型:常量
說明:字體的粗細。使用NORMALBOLD。默認為NORMAL

slant選項
類型:常量
說明:字體傾斜。使用NORMALITALIC。默認為NORMAL

underline選項
類型:標志
說明:字體下划線。如果1(true),字體加下划線。默認為0(false)

overstrike選項
類型:標志
說明:字體划線。如果為1(true),則字體上有一條線;默認為0(false)

3、系統字體

Tk也支持特定系統的字體名。在X下,這些通常是字體別名如fixed,6x10等等。

Windows下,這些包括ansi,ansifixed,device,oemfixed,systemsystemfixed


Macintosh上,系統字體名是applicationsystem

注意:系統字體是字體名,不是字體類型名,它們不能與尺寸或樣式屬性結合。為了可移植性,盡可能避免使用這些名字。

 

 


4X字體描述

X字體描述是如下格式的字符串(星號所代表的是無關字段。具體細節可查看Tk文檔或X手冊):
-*-family-weight-slant-*--*-size-*-*-*-*-charset

典型的字體類別如:Times, Helvetica, Courier or Symbol

weight可以是"Bold""Normal"slant取值中R代表"roman"(正常)I代表"italic"o代表團"oblique"(實際上等同於italic)。

size是字體的高度,以十分之一磅為單位。一英寸72磅,但是一些低分辯率的顯示器的1磅較常規的大些,以便小字體能夠清晰顯示。charset(字符集)通常是ISO8859-1 (ISO Latin 1), 但一些字體也使用其它的值。

下面的描述的family取值是Timesweight取值是Boldslant取值是Rsize取值是120charset取值是ISO8859-1
 -*-Times-Bold-R-*--*-120-*-*-*-*-ISO8859-1

如果你不關心charset(字符集),或你使用如Symbol的字體(這種字體類別有特定的字符集),那么你可以使用一個星號作為描述的最后部分:
-*-Symbol-*-*-*--*-80-*

型的X server至少支持Times, Helvetica, Courier等字體,size8, 10, 12, 14, 18, 24 磅,weightnormalbolditalic(Times)oblique(Helvetica, Courier)。大多數的服務器都有 支持隨意查看字體。你可以使用如xlsfontsxfontsel來檢查你所訪問的服務器的字體。

這種類型的字體描述可以用在Windows Macintosh上。注意:如果你使用Tk4.2,你必須牢記字體類型必須是Windows所支持的一種。

 格式化文本



雖然文本標簽和按鈕通常包含單行文本,但Tkinter也支持多行。要分離文本到多行,只需要在必要的地方插入換行符(\n)。

默認情況下,文本居中。你也可以通過設置justify選項為LEFTRIGHT來改變文本的位置。默認值是CENTER

你也可以使用wraplenth選項來設置一個最大寬度,並且讓窗口部件自己調整多行文本。如果窗口部件太窄,它將使單個詞跨行。

邊框



所有的Tkinter窗口部件都有邊框(盡管對於某些窗口部件默認是不顯示邊框的)。邊框由一個可選的3D浮雕和一個焦點高亮區域組成。

一、relief
這個relief設置控制如何繪制窗口部件的3D邊框:

borderwidth(bd)是邊框的寬度,以象素為單位。大多數的窗口部件都有一個默認的12象素的邊框寬度。

relief的取值可以有如下幾種:
SUNKEN, RAISED, GROOVE, RIDGE, and FLAT

二、焦點高亮
這個高亮設置控制如何指示窗口部件(或它的孩子之一)獲得了按鍵焦點。在大多數情況下,這個高亮區域是在relief外面的邊框。下面的選項控制如何繪制另外的邊框:

highlightcolor用來繪制當窗口部件獲得按鍵焦點的高亮區域。通常是黑色或別的明顯的對比色。
highlightbackground用來繪制當窗口部件沒獲得焦點的高亮區域。通常與窗口部件的背景色一樣。
highlightthickness選項是高亮區域的寬度,以象素為單位。對於那些獲得按鍵焦點的窗口部件通常是12個象素

三、光標
這個cursor選項控制當鼠標移動到窗口部件上時使用哪種鼠標光標。如果這個選項沒有設置,這個窗口部件將使用和它父親一樣的鼠標指針。

注意:一些窗口部件(包括TextEntry窗口部件)默認設置cursor選項。

下面是一些內建的鼠標光標的樣式:

 事件和綁定

 

 



正如早些時候,一個Tkinter應用程序大部分時間花費在事件循環中(通過mainloop方法進入事件循環)。事件來自不同的消息,包括用戶按下按鍵和鼠標操作,和來自於窗口管理器的重繪事件(在許多情況下不是由用戶直接引起)。

Tkinter提供了強大的機制讓你可以自己處理事件。對於任一窗口部件,你可以為事件綁定Python函數和方法:
widget.bind(event, handler)

如果發生在窗口部件中的事件與所描述的事件匹配,那么所給定的handler(處理器)將被描述這個事件的對象調用。

下面是一個捕獲窗口中的點擊的例子:
# File: bind1.py

from Tkinter import *

root = Tk()

def callback(event):
    print "clicked at", event.x, event.y

frame = Frame(root, width=100, height=100)
frame.bind("<Button-1>", callback)
frame.pack()

root.mainloop()
上面這個例子,我們使用了frame窗口部件的bind方法為一個事件調用<Button-1>綁定了一個回調函數。運行這個程序並在所顯示的窗口中點擊。每次點擊,在控制台窗口中都會打印一條如"clicked at 44 63"這樣的信息。

一、事件

事件以字符串的形式給出,使用特定的語法:
<modifier-type-detail>

type 字段是事件區分符中最重要的部分。它指定了我們希望去綁定的事件種類,如用戶的按鈕、按鍵動作,或如EnterConfigure等窗口管理器事件。 modifierdetail字段被用來給出附加的信息,在多數情況下可以不用。這兒也有不同的方法去簡化事件字符串;例如,要匹配一個鍵盤鍵,你可以 不用尖括號而只使用這個鍵。當然,除非它的一個空格或一個尖括號。

下面我們給出最常用的事件及其說明:

<Button-1>事件
明:鼠標按鈕在窗口部件上按下。button 1是鼠標左按鈕,button 2是鼠標中間的按鈕(如果有的話),button 3是鼠標右按鈕。當你在 一窗口部件上按下一個鼠標按鈕時,Tkinter將自動抓取鼠標指針,在鼠標按鈕被按下時鼠標事件將被發送給當前窗口部件。鼠標指針相對於窗口部件的當前 位置被提供給傳遞給回調函數的event對象的xy成員中。
你可以用 ButtonPress 代替Button,或只用<1>(這等同於<Button-1>, <ButtonPress-1>)。

<B1-Motion>事件
說明:鼠標移動並且鼠標左鍵被按住(B2代表鼠標中間按鍵,B3代表鼠標右按鍵)。鼠標指針相對於窗口部件的當前位置被提供給傳遞給回調函數的event對象的xy成員中。

<ButtonRelease-1>事件
說明:鼠標左鍵釋放。鼠標指針相對於窗口部件的當前位置被提供給傳遞給回調函數的event對象的xy成員中。

<Double-Button-1>事件
說明:鼠標左鍵雙擊。你可以用Triple代替Double

<Enter>事件
說明:鼠標指針位於窗口部件中(這個事件不代表回車)

<Leave>事件
說明:鼠標指針離開窗口部件。

<Return>事件
明:用戶按下Enter鍵。你可以綁定到鍵盤上的所有實際上的鍵。對於通常的102鍵盤,這專用鍵有 CancelBackSpaceTabEnterShift_LControl_LAlt_LPause, Caps_Lock, Escape, PageUp, Page Down, End, Home, Left, Up, Right, Down, Print, Insert, Delete, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, Num_Lock, Scroll_Lock

<Key>事件
說明:用戶按下任一鍵。這個鍵被提供給傳遞給回調函數的event對象的char成員中。

a事件
說明:用戶鍵入"a"。大部分的可打印字符都可替換a。這個例外是空格(<space>) 和小於(<less>)。

<Shift-Up>事件
說明:用戶按下向上箭頭,同時按住shift鍵。你可以用AltControl代替shift

<Configure>事件
說明:窗口部件的尺寸改變(某些平台上是位置改變)。新的尺寸被提供給傳遞給回調函數的event對象的widthheight屬性中。

二、Event對象

Event對象是一個標准的Python對象實例,它的屬性及說明如下:

widget
說明:產生事件的窗口部件。這是一個有效的Tkinter窗口部件的實例,不是一個名字。這個屬性為所有事件設置。

x,y
說明:當前鼠標指針的位置,以象素為單位。

x_root,y_root
說明:當前鼠標相對於屏幕左上方的位置,以象素為單位。

char
說明:字符代碼(僅鍵盤事件),是一個字符串。

keysym
說明:鍵的符號(僅鍵盤事件)。

keycode
說明:鍵的代碼(僅鍵盤事件)。

num
說明:鼠標按鈕的數字(僅鼠標按鈕事件)。

width,height
說明:窗口部件的新尺寸,以象素為單位(僅Configure事件)

type
說明:事件類型。

為了兼容性,你應堅持使用char, height, width, x, y, x_root, y_root, widget除非你確切地知道你在做什么。

三、實例和類綁定

上面的例子中我們使用bind方法創建一個實例綁定。這意味着這個綁定僅應用於單個窗口部件;如果你創建新的frame,它們將不繼承這個綁定。

但是Tkinter也允許你在類和應用程序層上創建綁定;事實上,你可以在下面四個不同的層上創建綁定:
*窗口部件實例,使用bind方法。
*窗口部件的頂層窗口(頂層或root),也使用bind方法。
*窗口部件類,使用bind_class方法(這是Tkinter提供的標准綁定)。
*整個應用程序,使用bind_all方法。

例如,你可以使用bind_all來為F1鍵創建一個到應用程序的綁定,這樣你就可以在這個應用程序的任何地方提供幫助。但是如果你為同一個鍵創建多個綁定或提供重疊的綁定會發生什么呢?

首先,對於上面四種層別之一的任何一種,Tkinter選擇有效綁定的最近匹配。例如,如果你為<Key><Return>事件創建了實例綁定,那么如果你按下了Enter鍵則只是這第二個綁定將被調用。

然而,如果你增加一個<Return>綁定到頂層窗口部件,則兩個綁定都會被調用。Tkinter首先調用實例層的綁定,然后調用頂層窗口層綁定,然后是類層(通常是一個標准綁定),最后是應用程序層。因此在極端的情況下,一個事件可以調用四個事件處理器。

一個引起混淆的情況是什么時候你使用綁定去覆蓋一個標准窗口部件的默認行為。例如,假設你希望Enter在文本窗口部件中無效,以使用戶不能在文本中插入新行。下面的代碼可以實現嗎?
def ignore(event):
    pass
text.bind("< http://www.bboby.com >", ignore)
或用下面一行代碼:
text.bind("<Return>", lambda e: None)

不幸的是,這個新行仍然插入了,因為上面的綁定僅應用於實例層,頁標准的行為是由類層的綁定提供。

你可以使用bind_class方法來修改類層上的綁定,但是這將改變應用程序中的所有文本窗口部件的行為。
一個簡單的解決方法是阻止Tkinter傳遞事件給別的處理器;並且你的事件處理器只返回"break"字符串:
    def ignore(event):
        return "break"
    text.bind("<Return>", ignore)



    text.bind("<Return>", lambda e: "break")

順便說說,如果你真想改變應用程序中的所有文本窗口部件的行為,可以使用bind_class方法:
top.bind_class("Text", "<Return>", lambda e: None)
但是基於很多原因你是不會這樣做的。例如,如果你希望使用從網上下載的一些酷而小的UI組件來擴展你的應用程序,這樣做將會將應用程序完全搞亂。較好的方法是使用你自己定制的文本窗口部件類,這樣就可以保持Tkinter默認綁定的完好:
    class MyText(Text):
        def __init__(self, master, **kw):
            apply(Text.__init__, (self, master), kw)
            self.bind("<Return>", lambda e: "break")

四、協議(protocols)

除了事件綁定,Tkinter也支持一個稱作協議處理器的機制。在這里,協議這個術語是指應用程序與窗口管理器之間的交互。最常被使用的協議名為WM_Delete_WINDOW,它被用來定義當用戶顯式使用窗口管理器關閉一個窗口時發生什么。

你可以使用protocol方法去為這個協議安裝一個處理器(窗口部件必須是root或頂層窗口部件):
widget.protocol("WM_Delete_WINDOW", handler)

一旦你安裝了你自己的處理器,Tkinter將不再自動關閉窗口。作為代替,比如你可以顯示一個信息框詢問用戶當前數據是否保存。要從處理器關閉窗口,你只需要調用這個窗口的destroy方法:
例子、捕獲destroy事件:
# File: protocol1.py

from Tkinter import *
import tkMessageBox

def callback():
    if tkMessageBox.askokcancel("Quit", "Do you really wish to quit?"):
        root.destroy()

root = Tk()
root.protocol("WM_Delete_WINDOW", callback)

root.mainloop()

注意:即使你在頂層窗口上不為WM_Delete_WINDOW注冊一個處理器,這個窗口自己也會照常被銷毀。然而,對於Python 1.5.2Tkinter將不會銷毀相應的窗口部件實例層,因此你自己注冊一個處理器是一個好的主意:
    top = Toplevel(...)

    # 確使用窗口部件實例被刪除
    top.protocol("WM_Delete_WINDOW", top.destroy)

五、其它的協議

口管理器協議是X window系統最初的部分(它們被定義在標題為Inter- Client Communication Conventions Manual文檔,或ICCCM中)。在那個平台上你也可以安裝別的協議,如 WM_TAKE_FOCUS WM_SAVE_YOURSELF。詳細請閱ICCCM文檔。

 

應用程序窗口



一、基本的窗口

先前我們使用了一個簡單的例子,它僅在屏幕上顯示一個窗口——root窗口。這是當我們調用Tk構造器時自動創建的,對於簡單的應用程序非常方便:
    from Tkinter import *

    root = Tk()
    
    # 這里可以創建窗口內容作為root窗口的孩子
    
    root.mainloop()

如果你要創建額外的窗口,你可以使用Toplevel窗口部件。它僅在屏幕上創建一個新的窗口,它的樣式和行為都很象原本的root窗口:
    from Tkinter import *
    
    root = Tk()
    
    # 創建root窗口內容
    
    top = Toplevel()
    
    # 創建頂層窗口內容
    
    root.mainloop()

這里不必要使用pack去顯示這個Toplevel,因為它是自動被窗口管理器顯示(事實上,如果你試圖對Toplevel窗口部件使用pack或別的geometry管理器,你將會得到一個錯誤信息)。

二、菜單

Tkinter為菜單提供了專門的窗口部件類型。要創建一個菜單,你要創建一個Menu類的實例,並且用add方法為這個實例增加條目:
* add_command(label=string, command=callback) 增加一個普通的菜單條目。
* add_separator() 增加一個分隔線。用來分組菜單條目。
* add_cascade(label=string, menu=menu instance) 增加一個子菜單。這是一個依附於父親的下拉菜單或折疊式菜單。

下面這個例子創建了一個小的菜單:
# File: menu1.py

from Tkinter import *

def callback():
    print "called the callback!"

root = Tk()

# create a menu
menu = Menu(root)
root.config(menu=menu)

filemenu = Menu(menu)
menu.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="New", command=callback)
filemenu.add_command(label="Open...", command=callback)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=callback)

helpmenu = Menu(menu)
menu.add_cascade(label="Help", menu=helpmenu)
helpmenu.add_command(label="About...", command=callback)

mainloop()

在上面的例子中,我們通過創建一個Menu實例開始,然后我們使用config方法將這個菜單實例隸屬於root窗口。這個菜單的內容將被用來去創建一個位於root窗口頂部的菜單條。你不必pack這個菜單,因為它被Tkinter自動顯示。

下來,我們創建一個新的Menu實例,使用菜單條作為這個新實例的父親,並且使用add_cascade方法使用它成為一個下拉式菜單。然后我們調用 add_command來給這個菜單添加命令(注意在這個例子中所有的命令都使用相同的回調函數),並使用add_separatorfile命令和 exit命令之間添加一個分隔線。

最后我們以同樣的方式創建一個小的幫助菜單。

三、工具條

許多應用程序都在菜單條下面放置了一個工具條,通常都包含了一定量的按鈕以完成通常的功能如open,file,print,undo等等。

下面的例子,我們使用一個Frame部件作為一個工具條,並放置上一定量的通常的按鈕:
# File: toolbar1.py

from Tkinter import *

root = Tk()

def callback():
    print "called the callback!"

# create a toolbar
toolbar = Frame(root)

b = Button(toolbar, text="new", width=6, command=callback)
b.pack(side=LEFT, padx=2, pady=2)

b = Button(toolbar, text="open", width=6, command=callback)
b.pack(side=LEFT, padx=2, pady=2)

toolbar.pack(side=TOP, fill=X)

mainloop()

按鈕以左邊對齊,工具條自身放置在最上面(將fill設置為X)。
注意:這里我使用文本標簽,而沒有使用圖標,這樣更簡單。要顯示一個圖標,你可以用PhotoImage構造器來從磁盤裝載一個小的圖象,並使用image選項去顯示它。

四、狀態條

大多數應用程序都在應用程序窗口的底部顯示一個狀態條。用Tkinter實現一個狀態條是很容易的:你可以簡單地使用一個合適的可配置的Label窗口部件,而后重新配置這個text選項。這里有一個方法:
    status = Label(master, text="", bd=1, relief=SUNKEN, anchor=W)
    status.pack(side=BOTTOM, fill=X)

如果你希望有想象力,你可以使用下面的類來代替。它在類中封裝了一個label窗口部件,並提供了setclear方法來修改內容:
# File: tkSimpleStatusBar.py

class StatusBar(Frame):

    def __init__(self, master):
        Frame.__init__(self, master)
        self.label = Label(self, bd=1, relief=SUNKEN, anchor=W)
        self.label.pack(fill=X)

    def set(self, format, *args):
        self.label.config(text=format % args)
        self.label.update_idletasks()

    def clear(self):
        self.label.config(text="")
        self.label.update_idletasks()

set方法類似於Cprintf函數;它要求一個格式字符串,后或許跟一套參數(缺點是如果你希望打印任意的字符串,你必須這樣做 set("%s", string))。同樣注意這個方法調用update_idletasks方法以保證繪制操作(如狀態條更新)立即進行。你可以使用 通常的窗口部件語法創建並顯示這個狀態條:
    status = StatusBar(root)
    status.pack(side=BOTTOM, fill=X) 

 標准對話框之消息框



以前我們關注了在應用程序工作區域中放置的一些窗口部件,現在讓我們來關注GUI程序設計的另一重要部分:顯示對話框和消息框。

Tk4.2開始,Tk庫提供了一套標准對話框,它們可以被用來顯示消息框,和選擇文件與顏色。另外, Tkinter提供了一些簡單的對話框以讓你可以去要求用戶的整數、浮點數值和字符串。這些標准對話框盡可能使用特定平台的機制以得到相應的外觀。

一、消息框

tkMessageBox模塊提供了一個對消息框的接口。

使用這個模塊最容易的方法是使用這些便利的函數之一:showinfo, showwarning, showerror, askquestion, askokcancel, askyesno,或askretrycancel。它們有同樣的語法:
tkMessageBox.function(title, http://www.bboby.com e [, options])
這個title參數顯示在窗口的標題中,這個message顯示在對話框體中。你可以在消息中使用換行符("\n")以使消息占據多行。options可以被用來修改外觀。

這第一組的標准對話框被用來呈現信息。你提供標題和消息,這個些函數使用一個恰當的圖標顯示這些,當用戶按下OK時返回。返回值被忽略。

這有個例子:
    try:
        fp = open(filename)
    except:
        tkMessageBox.showwarning(
            "Open file",
            "Cannot open this file\n(%s)" % filename
        )
        return

下面是第一組標准對話框(showinfo, showwarning, showerror dialogs)的圖示:

 

 


 

 


 

 





這第二組被用來詢問問題。askquestion函數返回字符串"yes""no"(你可以使用options去修改所顯示的按鈕的數量和類型),例如:
    if tkMessageBox.askyesno("Print", "Print this report?"):
        report.print()

第二組(askquestionaskokcancel, askyesno, askretrycancel dialogs)的圖示:

 

 

 

 

 

 

 

 









二、消息框選項

如果標准的消息框不適合你的要求,你可以使用options來達到你的要求。
下面是消息框選項及說明:

default
類型:常量
說明:默認健:ABORT, RETRY, IGNORE, OK, CANCEL, YESNO(它們定義在tkMessageBox模塊中)

icon
類型:常量
說明:要顯示的圖標:ERROR, INFO, QUESTION, WARNING

message
類型:字符串
說明:要顯示的消息(函數的第二個參數)

parent
類型:窗口部件
說明:在哪個窗口的頂部放置消息框。當消息框關閉后,焦點將返回父窗口。

title
類型:字符串
說明:消息框標題(函數的第一個參數)

type
類型:常量
說明:消息框類型;即顯示哪個按鈕:ABORTRETRYIGNORE, OK, OKCANCEL, RETRYCANCEL, YESNO, YESNOCANCEL

 數據輸入



tkSimpleDialog模塊提供了一個針對如下簡單對話框的接口.

一、字符串

tkSimpleDialog中的askstring函數用於給用戶一個提示字符串。你指定這個對話框的標題和提示字符串,當用戶關閉對話框時函數返回。提示字符串可以包含換行符:

tkSimpleDialog.askinteger(title, prompt [,options])要求用戶輸入一個字符串值。如果用戶按下了Enter鍵或敲擊了OK,那么函數返回這個字符串。如果用戶通過按下Esc或敲擊Cancel或顯式地由窗口管理器關閉了這個對話框,則這個函數返回None
askstring的圖示:

 

 



下面是這個函數能夠使用的選項(options)及說明:
initialvalue
類型:字符串
說明:初始值。默認值是一個空字符串。

parent
類型:窗口部件
說明:對話框放置於哪個窗口上。當對話框關閉時,焦點將返回到父窗口。

二、數字值

askintegeraskfloat函數類似於askstring函數,但它們只分別接收整型和浮點數值。你也可以使用minvaluemaxvalue選項來限制輸入的范圍:

tkSimpleDialog.askinteger(title, prompt [, http://www.bboby.com ])要求用戶輸入一個整形值。如果用戶輸入的值不是一個有效的整數或浮點數值,一個消息框將顯示,並且這個對話框不會關閉。如同askstring函數,如果對話框被取消則函數返回None

tkSimpleDialog.askfloat(title, prompt [,options])同樣,函數返回一個浮點數值。

askinteger, askfloat圖示如下:

 

 

 

 





這兩個函數可以使用的選項及說明如下:
initialvalue
類型:整形或浮點數
說明:初始值。默認是一個空字符串。

parent
類型:窗口部件
說明:對話框放置於哪個窗口上。當對話框關閉時,焦點將返回到父窗口。

minvalue
類型:整形或浮點數
說明:最小值。如果低於,當用戶敲擊OK時一個消息框將顯示,並且對話框不會關閉。

maxvalue
類型:整形或浮點數
說明:最小值。如果高於,當用戶敲擊OK時一個消息框將顯示,並且對話框不會關閉。

三、文件名

tkFileDialog模塊(包含在早先說明的標准對話框工具包中)可以用來從用戶得到文件名。這個模塊提供了兩個方便的函數,一個用來得到已存在的文件名以便於你打開它,另一個用來得到一個新的文件名以保存東西。

tkFileDialog.askopenfilename([options])如果這個對話框被取消,則函數返回None

tkFileDialog.asksaveasfilename([options])

下面是askopenfilename, asksaveasfilename的圖示:

 

 

 

 



 

 



下面是options及說明:
defaultextension
類型:字符串
說明:文件名的后綴,如果用戶沒有顯示指定。字符串應該包含開頭的點號(打開對話框將忽略)

filetypes
類型:列表
說明:由(標簽,匹配模式)元組構成的序列。同一個標簽可以有幾個匹配模式。使用*作為模式表明所有文件。

initialdir
類型:字符串
說明:初始目錄。

initialfile
類型:字符串
說明:初始文件(打開對話框將忽略)。

parent
類型:窗口部件
說明:對話框放置於哪個窗口上。當對話框關閉時,焦點將返回到該窗口。

title
類型:字符串
說明:消息框標題。

四、顏色

tkColorChooser模塊(包含在早先說明的標准對話框工具包中)可以被用來指定一個RGB顏色值。

tkColorChooser.askcolor([color [,options]])這個函數返回兩個值;第一個是一個三元組(包含了代表紅、綠、藍三色的三個整數值(0~255),第二個是Tk顏色字符串。當你顯示這個對話框時要預定一個顏色,你可以傳遞一個顏色給這個函數。

如果對話框被取消,則函數返回(None,None

下面是askcolor的圖示:

下面是askcolorOptions及說明:

initialcolor
類型:顏色
說明:當對話框顯示時所標記的顏色(可以是RGB值或顏色名)

parent
類型:窗口部件
說明:對話框放置於哪個窗口上。當對話框關閉時,焦點將返回到該窗口。

title
類型:字符串
說明:消息框標題。
 
對話窗口



雖然前面部分所介紹的標准對話框對許多簡單的應用是足夠了,但是大多數較大的應用要求更復雜的對話框。例如,要為一個應用程序設置配置參數,你也許想在一個對話框中讓用戶輸入更多的信息。

基本上,創建一個對話窗口與創建一個應用程序窗口沒什么不同。僅僅是使用這個Toplevel部件,填充必要的輸入域,按鈕和其他一些窗口部件。(順便說一下,不要使用 ApplicationWindow 類,他只會讓你的用戶糊塗。)

下面的例子中,MyDialog類創建了一個Toplevel窗口部件,並在其上增加了一些窗口部件。然后使用wait_window來等待直到對話框被關閉。如果用戶敲擊OK,這個輸入域中的值將被打印,並且對話框被明確地銷毀。
# File: dialog1.py

from Tkinter import *

class MyDialog:

    def __init__(self, parent):

        top = self.top = Toplevel(parent)

        Label(top, text="Value").pack()

        self.e = Entry(top)
        self.e.pack(padx=5)

        b = Button(top, text="OK", command=self.ok)
        b.pack(pady=5)

    def ok(self):

        print "value is", self.e.get()

        self.top.destroy()


root = Tk()
Button(root, text="Hello!").pack()
root.update()

d = MyDialog(root)

root.wait_window(d.top)

注意:我們這兒沒有調用mainloop方法;使用wait_window來進入局部事件循環就足夠了。但是這個例子有一些問題:
* root窗口仍舊是活動的。當對話框顯示的時候你也可以敲擊root窗口上的按鈕。如果對話框依賴於當前應用程序狀態,那么讓用戶自己干預應用程序可能是災難性的。並且僅顯示多個對話框無疑會使用你的用戶糊塗。

* 你必須在輸入域中敲擊以使光標移入輸入域中,同樣必須敲擊按鈕。在輸入域中按下Enter鍵是不夠的。

*這里應該有一些控制方法來取消對話框(作為我們早先學習的,我們也應該處理WM_Delete_WINDOW 協議)。

針對第一個問題,Tkinter提供了一個名為grab_set的方法,它確保沒有鼠標或鍵盤事件被傳送給錯誤的窗口。

二個問題由幾個部分組成;首先我們需要明確地移動鍵盤焦點到對話框。這可以使用focus_set 方法做到。第二,我們需要綁定Enter鍵以使它調用 ok方法。這個容易,只需在Toplevel窗口部件上使用bind方法(並且確保修改ok方法,我們給了它一個可選的參數以使它不對event對象阻 塞)。

第三個問題可以通過增加一個額外的Cancel按鈕它調用destroy方法,並且當用戶按下了Esc或明確地關閉了窗口時使用bindprotocol來完成任務同樣的事。

下面的Dialog類提供了上面所有這些,和一些額外的技巧。要實現你自己的對話框,你可以簡單地繼承這個類並覆蓋bodyapply方法。這個前部分創建對話框體,后部分在用戶敲擊OK時被調用。
# File: tkSimpleDialog.py

from Tkinter import *
import os

class Dialog(Toplevel):

    def __init__(self, parent, title = None):

        Toplevel.__init__(self, parent)
        self.transient(parent)

        if title:
            self.title(title)

        self.parent = parent

        self.result = None

        body = Frame(self)
        self.initial_focus = self.body(body)
        body.pack(padx=5, pady=5)

        self.buttonbox()

        self.grab_set()

        if not self.initial_focus:
            self.initial_focus = self

        self.protocol("WM_Delete_WINDOW", self.cancel)

        self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
                                  parent.winfo_rooty()+50))

        self.initial_focus.focus_set()

        self.wait_window(self)

    #
    # construction hooks

    def body(self, master):
        # create dialog body.  return widget that should have
        # initial focus.  this method should be overridden

        pass

    def buttonbox(self):
        # add standard button box. override if you don't want the
        # standard buttons
        
        box = Frame(self)

        w = Button(box, text="OK", width=10, command=self.ok, default=ACTIVE)
        w.pack(side=LEFT, padx=5, pady=5)
        w = Button(box, text="Cancel", width=10, command=self.cancel)
        w.pack(side=LEFT, padx=5, pady=5)

        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.cancel)

        box.pack()

    #
    # standard button semantics

    def ok(self, event=None):

        if not self.validate():
            self.initial_focus.focus_set() # put focus back
            return

        self.withdraw()
        self.update_idletasks()

        self.apply()

        self.cancel()

    def cancel(self, event=None):

        # put focus back to the parent window
        self.parent.focus_set()
        self.destroy()

    #
    # command hooks

    def validate(self):

        return 1 # override

    def apply(self):

        pass # override

要的技巧在構造器中實現。首先,transient將這個窗口與一個父窗口相關聯(通常是引起這個對話框的應用程序窗口)。對話框不會以圖標的形式顯示在 窗口管理器中(例如,在Windows下,對話框不會出現在任務欄中),如果你將父窗口圖標化,那么對話框也將隱藏。接下來,構造器創建對話體,然后調用 grab_set設置對話框模式,geometry布置對話框相對於窗口的位置,focus_set移動焦點到適當的窗口部件(通常是使用body方法返 回的窗口部件),最后wait_window

注意我們使用protocol方法來確保一個明確的關閉被當作cancel(取消),並且在buttonbox 方法中,我們綁定Enter鍵到OKEscCanceldefault=ACTIVE調用標記這個OK按鈕為特定平台的默認按鈕方式。

使用這類比摸清它是如何實現的容易的多;只需要在body方法中創建必要的窗口部件,在apply方法中取得結果和執行你想做的。
下面是一個簡單的例子:
# File: dialog2.py

import tkSimpleDialog

class MyDialog(tkSimpleDialog.Dialog):

    def body(self, master):

        Label(master, text="First:").grid(row=0)
        Label(master, text="Second:").grid(row=1)

        self.e1 = Entry(master)
        self.e2 = Entry(master)

        self.e1.grid(row=0, column=1)
        self.e2.grid(row=1, column=1)
        return self.e1 # initial focus

    def apply(self):
        first = string.atoi(self.e1.get())
        second = string.atoi(self.e2.get())
        print first, second # or something

運行dialog2.py 結果如下:

 

 


注意當對話框顯示的時候,這個body方法可以隨意地返回應該獲得焦點的窗口部件。假如這與你的對話框無關,則只返回None(或者省略return語句)。

上面的例子在apply方法中執行實際的處理。但是代替在apply方法中的處理,你可以存儲所鍵入的數據到一個實例的屬性中:
        def apply(self):
            first = int(self.e1.get())
            second = int(self.e2.get())
            self.result = first, second
    
    d = MyDialog(root)
    print d.result
意如果對話框被取消了,則apply方法不會被調用,並且result屬性沒有被設置。這個對話框構造器設置這個屬性為None,以便於在處理之前你可以 簡單地測試這個結果。如果你想返回數據到其它的屬性中,請確保在body方法中初始化它們(或簡單地在apply方法中設置result1,並在文章其 它屬性之前測試它)。

格子布置

我們在設計應用程序窗口時的所使用的方便的pack管理器在對話框的應用中確不是那么容易使用。一個典型的對話框可能包括一定數量的輸入域和復選框,和相應的標簽。考慮如下的簡單例子:

例:簡單對話框的布置

 

 


pack管理器來實現它,我們可以創建一個frame來包含標簽"first:",和相對應的輸入域,並當pack它們時使用"side=LEFT"。 為下一行增加一個相應的frame,並使用"side=TOP"pack這些framescheckbutton到一個外部的frame。不幸的,使用 這個方式pack標簽則可能得到輸入域的列隊,並且如果我們替換為使用"side=RIGHT"pack輸入域,如果輸入域有不同的寬度則事情將破壞。 通過仔細地使用widthsize等等選項,我們可以努力得到合適的結果。但是這兒有一個非常容易的方法:使用grid管理器。

grid管理器把主窗口部件(典型的是一個frame)分成一個二維的格子或表。對於每個窗口部件,你只需要指定它出現在格子的哪兒,其余就由grid管理器去操心吧。下面的body方法顯示了如何得到上面的布局:
例子:使用grid geometry管理器
# File: dialog3.py

def body(self, master):

    Label(master, text="First:").grid(row=0, sticky=W)
    Label(master, text="Second:").grid(row=1, sticky=W)

    self.e1 = Entry(master)
    self.e2 = Entry(master)

    self.e1.grid(row=0, column=1)
    self.e2.grid(row=1, column=1)

    self.cb = Checkbutton(master, text="Hardcopy")
    self.cb.grid(row=2, columnspan=2, sticky=W)

個窗口部件將由grid管理器處理,你需要調用grid方法並使用rowcolumn選項來告訴管理器把窗口部件放置在哪兒。最上面一行和最左一列的數 值是0(這也是一個默認值)。這時checkbutton被放置在labelentry窗口部件的下面,columnspan選項用來使它占據多個單元 格。結果如下:

 

 


如果你看仔細點,你將發現這個對話框與dialog2.py的對話框有一點不同。這里,標簽是左對齊的。如果你比較下代碼,你將發現唯一的不同是一個名為sticky的選項。

顯示frame窗口部件時,grid geometry管理器遍歷所有的窗口部件,為每行每列計算出一個合適的寬度和高度。如果單元格大於窗口部件,則窗 口部件是默認居中的。sticky選項被用來修改這個行為。通過設置它為E, W, S, N, NW, NE, SE, SW之一,你能夠與單元格的任 一邊或角對齊。但是如果有必要,你也可以使用這個選項去伸展窗口部件;如果你設置這個選項為E+W,則這個窗口部件將伸展為占據單元格的整個寬度。如果設 置為E+W+N+S(或NW+SE等),窗口部件將兩個方向都伸展。實際上,這個sticky選項代替了通過pack管理器使用的 fill,expand,anchor選項。

grid管理器提供了許多其它的選項讓你去調整結果布局的外觀和行為。

確認數據



如果用戶鍵入的數據不對怎么辦?在我們當前的例子中,如果輸入域中的內容不是一個整數apply方法將引發一個異常。我們當然可以用一個try/except 和一個標准信息框來處理這個:
    def apply(self):
        try:
            first = int(self.e1.get())
            second = int(self.e2.get())
            dosomething((first, second))
        except ValueError:
            tkMessageBox.showwarning(
                "Bad input",
                "Illegal values, please try again"
            )
里有一個問題:當apply方法被調用時,這個ok方法已經將對話框從屏幕上去除,並且我們一返回它就將它銷毀。這個設計是有意的;如果我們在apply 方法中執行一些潛在冗長的處理,假如在我們完成之前對話框沒被去除那將是非常混亂的。Dialog類已經包含了鈎子以實現另一方案:一個單獨的 validate方法,它在對話框被去除之前調用。

在下面的例子中,我們簡單地將apply中的代碼移到validate中,並且改變為存儲結果到實例的屬性中。
        def validate(self):
            try:
                first= int(self.e1.get())
                second = int(self.e2.get())
                self.result = first, second
                return 1
            except ValueError:
                tkMessageBox.showwarning(
                    "Bad input",
                    "Illegal values, please try again"
                )
                return 0
        
        def apply(self):
            dosomething(self.result)
 



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM