1 基本概念
對話框是通過腳本彈出的視窗,向使用者提供或要求額外資訊。按照類型可以分為兩類,模态和非模态。
模态: 會阻止其他界面,知道對話框被關閉。
非模态:可以永久停留在螢幕上,而且不會幹擾界面中的其他視窗,可以接受輸入(随時)。
建立對話框的三種方法:
1)調用通用對話框
2)通過目前的Dialog 對象 [比較過時了]
3)通過與Toplevel和其他元件一同建立自定義對話框視窗
2 标準(通用)對話框[模态]
标準對話框類型: 檔案選擇對話框 / 錯誤和警告彈出式視窗 / 提問及回答彈出式視窗
示例代碼:提供四種通用對話框。
from tkinter import *
from tkinter.messagebox import *
def callback():
if askyesno('Verify', 'Do you really want to quit?'):
showwarning('Yes', 'Quit not yet implemented')
else:
showinfo('No', 'Quit has ben canceled')
errmsg = 'Sorry, no Spam allowed!'
Button(text = 'Quit', command = callback).pack(fill=X)
Button(text = 'Spam', command = (lambda:showerror('Spam', errmsg))).pack(fill= X)
mainloop()
從左至右,1,2,3,4.
1) askyesno( 視窗标題, 提示字元串) 建立對話框,提供Yes 和 No兩個選項;
2) showwarning(視窗标題, 提示字元) 建立警告對話框,一個OK按鈕和警告辨別;
3)showinfo(視窗标題, 提示字元) 一個感歎号加OK按鈕;
4)showerror(标題, 提示字元) 一個❌和OK按鈕;
對話框複用編碼方式: 這個例子比較幹,就是按鈕點選事件綁定了對話框事件。
from tkinter import *
from tkinter.messagebox import askokcancel
class Quitter(Frame): # 依托于架構建立
def __init__(self, parent = None):
Frame.__init__(self, parent)
self.pack()
widget = Button(self, text='Quit', command = self.quit)
widget.pack(side=LEFT, expand=YES, fill = BOTH)
def quit(self):
ans = askokcancel('Verify exit', 'Really quit?')
if ans:
Frame.quit(self) # 調用Frame的quit用來退出對話框
if __name__ == '__main__':
Quitter().mainloop()
GUI例子:對話框示範啟動欄 [字典驅動式程式設計]
from tkinter.filedialog import askopenfilename # 标準檔案對話框
from tkinter.colorchooser import askcolor
from tkinter.messagebox import askquestion, showerror
from tkinter.simpledialog import askfloat
demos = {
'Open':askopenfilename,
'Color':askcolor,
'Query':lambda:askquestion('Warning', 'You type "rm *"\nConfirm?'),
'Error':lambda:showerror('Error!', "He's dead, Jim"),
'Input':lambda:askfloat('Entry', 'Enter credit card number')
}
class Demo(Frame):
def __init__(self, parent=None, **options): # **options 傳遞關鍵字參數到Frame超類的構造函數中,并生效
Frame.__init__(self, parent, **options)
self.pack()
Label(self,text = 'Basic demos').pack()
for (key, calue) in demos.items():
Button(self, text = key, command = value).pack(side=TOP,fill=BOTH)
Quitter(self).pack(side=TOP,fill=BOTH) # 引用前面定義的退出按鈕
使用到的對話框說明:
1) 文本選擇對話框
2)顔色選擇對話框
3)問詢對話框
4)錯誤資訊提示對話框
5)浮點數輸入對話框
具體效果,從左往右,依次1,2,3,4,5.
2.1 askquestion/ askyesno/ askokcancel
askquestion 傳回 字元串 “Yes" 或 ”No“
askyesno / askokcanel 傳回 True 或 False
2.2 askfloat / askinteger / askstring
askfloat 傳回浮點數; askinteger 傳回整數; askstring 傳回字元串; 點選cancl ,傳回None
2.3 askopenfilename 選擇檔案
按下Open,傳回 完整的目錄路徑;按下 cancel 傳回空的字元串
askopenfilename 可以接受的關鍵字參數:
- filetypes 選擇檔案的名稱模式,出現在靠近對話框的底部的下拉菜單
-
initialdir 起始目錄
3)initialfile 檔案名
4)title 對話框标題
5)defaultextension 沒有進行選擇時的預設
6) parent 顯示為一個嵌入式的子集,非彈出框
2.4 askdirectory 選擇檔案夾目錄
于 askopenfilename 類似
2.5 askcolor 顔色選擇對話框
傳回RGB顔色值和十六進制字元串, 如 ((160,160,106), “a0a0a0”)
3 擷取對話框的輸出,使用lambda函數傳遞回調資料
from tkinter.filedialog import askopenfilename # 标準檔案對話框
from tkinter.colorchooser import askcolor
from tkinter.messagebox import askquestion, showerror,askokcancel
from tkinter.simpledialog import askfloat
from tkinter import *
demos = {
'Open':askopenfilename,
'Color':askcolor,
'Query':lambda:askquestion('Warning', 'You type "rm *"\nConfirm?'),
'Error':lambda:showerror('Error!', "He's dead, Jim"),
'Input':lambda:askfloat('Entry', 'Enter credit card number')
}
class Quitter(Frame): # 依托于架構建立
def __init__(self, parent = None):
Frame.__init__(self, parent)
self.pack()
widget = Button(self, text='Quit', command = self.quit)
widget.pack(side=LEFT, expand=YES, fill = BOTH)
def quit(self):
ans = askokcancel('Verify exit', 'Really quit?')
if ans:
Frame.quit(self) # 調用Frame的quit用來退出對話框
class Demo(Frame):
def __init__(self, parent=None, **options): # **options 傳遞關鍵字參數到Frame超類的構造函數中,并生效
Frame.__init__(self, parent, **options)
self.pack()
Label(self,text = 'Basic demos').pack()
for (key, calue) in demos.items():
func = (lambda key=key: self.printit(key)) # 這很重要
Button(self, text = key, command = func).pack(side=TOP,fill=BOTH)
Quitter(self).pack(side=TOP,fill=BOTH) # 引用前面定義的退出按鈕
def printit(self, name):
print(name, 'return =>', demos[name]())
if __name__ == "__main__":
Demo(bg='blue').mainloop()
** lambda 的表達式必須寫成 lambda key = key: self.printit(key) !!!【通過預設參數顯示的傳遞變量】**
分析:如果去掉 key = key,在回調的時候, key将一直是最後一個傳入的變量;通過 key=key,改變lambda内部的變量。
用一個可調用的類,來代替lambda函數的效果,相關的狀态儲存在類的self中。
class savekey:
def __init__(self, name):
self.name = name
def __call__(self):
print(self.name, "return =>", demos[self.name]())
4 對話框應用編碼
4.1 使用者選擇視窗的顔色
from tkinter import *
from tkinter.colorchooser import askcolor
def setBgColor(): # 使用了全局變量
(triple, hexstr) = askcolor()
if hexstr:
print(hexstr)
push.config(bg = hexstr)
root = Tk()
push = Button(root, text='Set Background Color', command = setBgColor)
push.config(height=3, font=('times', 20, 'bold'))
push.pack(expand=YES, fill=BOTH)
root.mainloop()
4.2 自定義對話框——建立模态對話框
方法1:focus_set/ grad_set() /wait_window
import sys
from tkinter import *
makemodal = (len(sys.argv) > 1)
def dialog():
win = Toplevel()
Label(win, text = 'Hard drive reformatted!').pack()
Buuton(win, text = 'OK', command=win.destroy).pack()
if makemodal:
win.focus_set() # 獲得輸入焦點
win.grad_set() # 在打開該視窗的時候,禁止其他視窗
win.wait_window() # win銷毀之前,繼續等待
print('dialog exit')
root = Tk()
Button(root, text='popup', command=dialog).pack()
root.mainloop()
方法二:mainloop 和 quit組合
from tkinter import *
def dialog():
win = Toplevel()
Label(win, text='Hard drive reformatted!').pack()
Button(win,text='OK', command=win.quit).pack()
win.protocol('WM_DELETE_WINDOW', win.quit)
win.focus_set()
win.grab_set()
win.mainloop()
win.destroy()
print('dialog exit')
root = Tk()
Button(root, text='popup', command=dialog).pack()
root.mainloop()
這種方法,需要在對話框内部調用quit,而不是在對話框回調處理器中調用,這是指調用destroy,他不會終止mainloop級别。protocol視窗也需要調用quit。
建議使用方法一。