天天看点

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。

建议使用方法一。