天天看點

tkinter标準對話框及回調擷取對話框傳回1 基本概念2 标準(通用)對話框[模态]3 擷取對話框的輸出,使用lambda函數傳遞回調資料4 對話框應用編碼

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.

tkinter标準對話框及回調擷取對話框傳回1 基本概念2 标準(通用)對話框[模态]3 擷取對話框的輸出,使用lambda函數傳遞回調資料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.

tkinter标準對話框及回調擷取對話框傳回1 基本概念2 标準(通用)對話框[模态]3 擷取對話框的輸出,使用lambda函數傳遞回調資料4 對話框應用編碼

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 可以接受的關鍵字參數:

  1. filetypes 選擇檔案的名稱模式,出現在靠近對話框的底部的下拉菜單
  2. 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。

建議使用方法一。