Python Tkinter里取回button 回调函数的变量

这篇博客介绍了在Python Tkinter中如何从Button的回调函数中获取变量值。作者通过示例代码展示了在点击Button后如何正确获取并保存文件路径,讨论了mainloop的工作原理以及组件销毁的影响。最后强调了理解变量绑定和组件生命周期的重要性。

Python Tkinter里取回button 回调函数的变量

最近在尝试用用python的内置库tkinter写一个GUI应用,碰到了一些问题,这里note一下。
开发工具:pycharm
库:Tkinter
python 版本: python3.6

Button 组件介绍

buttonTkinter里实现的是一个按钮功能。但是这里想实现取出command=func 中回调函数的变量值,因为在点击button
回调函数才开始被调用,但是语句self.button = Button(command = func) 执行后self.button 接收的是.!application.!button,即使在
get_file_path实例方法内添加return self.file_name , 结果还是一样的,而且这个结果是在程序Run后不需要点击button就打印了
,即button创建的时候就打印了。
Tips: 如果把command = func 改成command = print('hello world') , 即把command=后的函数名直接写成语句,那么button不需要点击就会在创建的时候执行这个语句,所以一般可以在语句前加上 匿名函数lambda , 这里是lambda: print('Hello world'), Button就会在点击后才打印Hello World, 匿名函数实现了延迟调用的效果,这里具体怎么实现的还有待考究,如果知道的大神可以帮忙分析一波。

代码分析

先看一下代码

from tkinter import *
from tkinter.filedialog import askopenfilename
class Application(Frame):
    def __init__(self, parent=None):    #这里重写Application的父容器Frame,从而让其成为顶级容器
        Frame.__init__(self, parent)    #父容器Frame的parent是TK(),这个是所tkinter的组件的主窗口
        self.pack(expand=YES)           #打包application, tkinter会自动为其画一个矩形框,其所有的子部件将在这个矩形框里布局
                                                        #如果没有这个pack(),所有继承self的子类将都不会出现在主窗口中,表现形式上就是主窗口是个空的。
        self.create_widget()

    def create_widget(self):            #创建组件
        self.lab = Label(self, text='File_Path').grid(row=0, column=0)
        self.ent = Entry(self, width=40)
        self.ent.grid(row=0,column=1)
        self.button = Button(self, text='Open', command=self.get_file_path).grid(row=0, column=2)
        self.button = Button(self, text='submit', command=self.submit).grid(row=1,column=0)

    def get_file_path(self):         #获取文件路径
        self.ent.delete(0, END)      #先清空文件名框内的内容
        self.file_name = askopenfilename(filetypes=[('All Files', '.zip'),('All Files','.csv'))  #弹出文件复选框,选择文件,可以指定文件类型以过滤
        self.ent.insert(END, self.file_name)    #显示文件名,用insert方法把文件名添加进去

    def submit(self):                    #点击提交的时候获取button内回调函数的变量值,这里是文件路径
        self.file_path = self.ent.get()  #用组件Entry的get获取输入框内的字符串,其在组件被销毁前就被取到
        self.destory()                   #中断循环,即主程序跳出无限循环mainloop(),但是这里是销毁的Frame组件,因为self指的是Frame的派生
        #root.destroy()                  #同样是跳出mainloop(),但是这里销毁的是主窗口Tk(),默认情况下它是所有tkinter 组件的父容器

#root = Tk()                             #将主窗口实例化
app = Application()                      #将application实例化
app.mainloop()
print(app.file_path)                     #打印组件button 回调函数的变量

程序运行后会出现如下所示的GUI界面, 这是个获取文件全路径的GUI
在这里插入图片描述
点击open后就会弹出文件复选框,
在这里插入图片描述
但选择文件后,文件名会出现在file_path路径后
在这里插入图片描述
点击submit, 会出现一个有趣的现象,Frame内的内容不见了,因为程序执行了self.destory() 后这里的Frame就被销毁了,但是主窗口还在,同时我们发现命令行还没有打印出app.file_path的变量值。
在这里插入图片描述
为什么呢,思考一下,三秒钟。1,2,3
好,继续往下看, 你应该发现了

因为mainloop函数还在执行啊,mainloop还在无限循环中,也就是说上述的代码其实一直在app.mainloop()中,并没有退出来

app.mainloop()     #在这里循环,等待消息

那么这样才会结束这个循环跳出来执行循环外的语句体呢? 必须等被主窗口关掉,循环才会结束。

tkinter内所有的组件都是以类的继承来实现组件上的层级结构的,也就是说刚才被销毁的Frame就是上面这个主窗口的二级组件,它的活动范围也将被限定在这个主窗口内。

既然必须关闭主窗口,那我们直接点击这个空白窗口右上角的X就行了, 点击关闭后,发现命令行打印出了文件路径,也就是说
程序执行了最后一行语句print(app.file_path)

在这里插入图片描述
如果我们代码作如下修改, 在submit内注释掉对Frame的销毁,换成对root的销毁,同时这里需要在主程序中去掉root = Tk()的注释。

def submit(self):  
	... ... 
	#self.destroy()
	root.destroy()   

root = Tk()  

再运行一下程序,我们发现点击submit后,主窗口直接关闭了,同时命令行打印出了文件路径的信息。 这正符合我们的预期,
因为root就是主窗口Tk()的实例,我们在实例方法submit里销毁的是主窗口。组件在被销毁前,我们就已经取到了变量值。
当然,如果在组件被销毁之后取值也就会失败。这里取的值是从组件Entry里得来的,Entry在这个应用里的层级结构是三级组件。因为Entry被实例化的时候指定了其
父容器为self,即Application类,所以当实例app被销毁后,其子类的实例也会一起被销毁,即组件被销毁后,其所有子类的组件都被被销毁。

这里再思考一个问题,为什么实例app 被销毁了,我们还可以打印出它的属性值呢。
这里不要误会了,我的理解是此销毁非内存销毁,而是GUI组件被关闭了,只要在组件被关闭之前取到了组件或子组件的相关变量,它就可以在内存中保存下来。从而在组件被关闭的情况下继续被使用。

总结

关于在tkinterbutton组件的变量获取关键是理解destory()mainloop()的作用机制,再就是要知道
哪些获取变量的方法。

在tkinter模块库中,绑定在组件上的变量是变量类的实例,这些类是StringVar, Intvar,DoubleVar;具体要使用哪一个类要根据具体情况而定。比如,StringVar类的实例可以与一个Entry框相关。关于这一块大家可以参考《Python 编程》一书,里面对tkinter有一个很系统的讲解,虽然很多专有名字我也听不懂,但是搭配着《python学习手册》还有网上的各种资料,还是可以慢慢看懂的。

我是一只想做程序猿的通信汪!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值