Tkinter库的学习记录06-变量类别
6、变量类别6-1 变量类别的基本概念有些widget控件在执行时会更改内容例如文本框(Entry)、选项按钮(Radio button)等。有些我们可以更改他们的内容例如标签Label等。如果想要更改它们的内容可以使用这些控件的参数例如textvariable、variableonvalue等。不过要将Widget控件的参数以变量方式处理时需要借助tkinter模块内的变量类别(Variable Classes)这个类别有4个子类别每一个类别其实是一个数据类型的构造方法我们可以通过这4个子类别的数据类型将它们与Widget控件的相关参数结合。x IntVar() # 整形变量默认是0 x DoubleVar() # 浮点型变量默认是0.0 x StringVar() # 字符串变量默认是 x BooleanVar() # 布尔型变量True是1False是06-2 get()与set()可以使用get()方法取得变量内容使用set()方法设置变量内容。下面程序实例set()方法的应用。这个程序在执行时若单击Hit按钮可以显示I like tkinter字符串如果已经显示字符串则改成不显示字符串。这个程序第17行是将标签内容设为变量x第8行是设置显示标签时的标签内容第11行则是将标签内容设为空字符串以不显示标签内容。from tkinter import * def btn_hit(): global msg_on if msg_on False: msg_on True x.set(I lie tkinter) else: msg_on False x.set() root Tk() root.title(ch6_1) msg_on False x StringVar() label Label(root, textvariablex, fgblue, bglightyellow, fontVerdana 20 bold, width25, height2) label.pack() btn Button(root, textClick Me, commandbtn_hit) btn.pack() root.mainloop()运行结果在上述实例中利用布尔值msg_on变量判断是否要显示I lkie tkinter字符串如果msg_on是False表示没有显示I lkie tkinter字符串如果msg_on是True表示目前有显示I lkie tkinter字符串。当单击Click Me按钮时会更改msg_on状态可参考第7行和第10行。同时也由set()方法更改label对象的参数textariable的内容第8行设置显示I lkie tkinter字符串第11行设置不显示I lkie tkinter字符串。上述程序尽管可以运行可是并没有使用本节中另一个get方法()这个方法可以取得Widget控件某参数的变量内容我们将时殷弘下列程序进行改良。下面程序重新设计上面程序取消布尔值msg_on变量我们可以直接由get()方法获得目前Widget控件参数内容然后由此内容判断是否显示I lkie tkinter字符串。判断方式是如果目前是空字符串zhixi则显示I lkie tkinter字符串如果不是空字符串则改成显示空字符串。from tkinter import * def btn_hit(): if x.get() : x.set(I lie tkinter) else: x.set() root Tk() root.title(ch6_1) x StringVar() label Label(root, textvariablex, fgblue, bglightyellow, fontVerdana 20 bold, width25, height2) label.pack() btn Button(root, textClick Me, commandbtn_hit) btn.pack() root.mainloop()执行结果与上面代码一致。6-3 追踪trace()使用模式w了解6-2节的变量设置后我们可以利用变量设置追踪Widget控件当其内容更改时让程序执行callback函数。下面程序设计当Widget控件Entry内容改变时在Python Shell窗口中输出Entry content changed!。from tkinter import * def callback(*args): print(data chnaged: , x.get()) root Tk() root.title(ch6_3) x StringVar() entry Entry(root, textvariablex) entry.pack(padx10, pady5) x.trace(w, callback) # 若是有更改执行callback root.mainloop()运行结果在看到上述窗口输出时也可以在Python Shell窗口中看到下列输出。上面程序的重点是x.trace(w, callback) # w其实是write的缩写第一个参数是模式w代表当有执行写入时就自动去执行callback函数。也可以自行取函数名称这个动作称为变动追踪。我们可以通过x变量类别追踪Widget控件内容的改变时执行特定动作本实例是在Python Shell窗口中输出Entry的内容。上述程序的另一个重点内容如下def callback(*args):后续将说明上述*args参数的含义。下面程序扩充上述实例同时在Entry控件下方建立Label控件当在Entry中有输入时同时在下方的Label控件中显示。from tkinter import * def callback(*args): xL.set(xE.get()) print(data chnaged: , xE.get()) root Tk() root.title(ch6_3) xE StringVar() entry Entry(root, textvariablexE) entry.pack(padx10, pady5) xE.trace(w, callback) # 若是有更改执行callback xL StringVar() label Label(root, textvariablexL) xL.set(同步显示) label.pack(padx10, pady5) root.mainloop()运行结果6-4 追踪trace()使用模式r上一节介绍了当Widget控件内容更改时执行追踪并执行特定函数其实我们也可以设计当控件内容被读取时执行追踪并执行特定函数。下面程序扩展与修改上面的代码增加一个“读取”按钮当在Entry中输入数据时Python Shell窗口不显示数据但是下方的Label将同步显示。主要功能是如果单击了“读取”按钮系统将发出数据被读取的警告同时输出所读取的数据。from tkinter import * def callbackW(*args): xL.set(xE.get()) def callbackR(*args): print(Warning: 数据被读取!) def hit(): print(读取数据: , xE.get()) root Tk() root.title(ch6_5) xE StringVar() entry Entry(root, textvariablexE) entry.pack(padx10, pady5) xE.trace(w, callbackW) # 若是有更改执行callback xE.trace(r, callbackR) # 若是有被读取执行callback xL StringVar() label Label(root, textvariablexL) xL.set(同步显示) label.pack(padx10, pady5) btn Button(root, text读取, commandhit) btn.pack(pady5) root.mainloop()运行结果上述程序的重点是xE.trace(r, callbackR) # r其实是read缩写上述第一个参数是模式r代表当执行读取时就会自动会执行callbackR函数。也可以自行取函数名称这个动作称为读取追踪。我们可以通过xE变量类别追踪Widget控件内容被读取时执行的特定动作本实例是在Python Shell窗口输出Warning: 数据被读取和Entry中的内容。6-5 trace()方法调用的callback方法参数参考上面的内容def callback(*args):其实是传递三个参数分别是tk变量名称、index索引、mode模式。不过目前有关tk变量名称和index索引部分尚未完成实际支持至于第三个参数则是可以列出是r或w模式。由于我们所设计的程序并不需要传递参数所以可以直接用*args当作参数内容。下面程序列出trace()方法所调用callback()方法内的参数。from tkinter import * def callbackW(name, index, mode): xL.set(xE.get()) print(name %r, index %r, mode %r % (name, index, mode)) root Tk() root.title(ch6_5) xE StringVar() entry Entry(root, textvariablexE) entry.pack(padx10, pady5) xE.trace(w, callbackW) # 若是有更改执行callback xL StringVar() label Label(root, textvariablexL) xL.set(同步显示) label.pack(padx10, pady5) root.mainloop()运行结果6-6 计算器的设计在4-3节有介绍过简易计算器按钮布局的设计在5-9节有介绍过eval()方法的用法本章已经学会了使用变量类别控制标签的输出其实有这些概念就可以设计简单的计算器了。下面将介绍完整的计算器设计。下面程序中设计简易的计算器这个程序中在按钮设计时大量使用Lambda主要是因为数字按钮与算术表达式按钮使用相同的函数只是传递的参数不一样所以用Lambda可以简化设计。from tkinter import * def calculate(): result eval(equ.get()) equ.set(equ.get() \n str(result)) def show(buttonString): content equ.get() if content 0: content equ.set(content buttonString) def backspace(): # 删除最后一个字符 equ.set(equ.get()[:-1]) def clear(): # 清除显示区重置为0 equ.set(0) root Tk() root.title(计算器) equ StringVar() equ.set(0) # 默认显示0 # 设计显示区 label Label(root, width25, height2, reliefraised, anchorSE, textvariableequ) label.grid(row0, column0, columnspan4, padx5, pady5) # 清除显示区按钮 clearButton Button(root, textC, fgblue, width5, commandclear) clearButton.grid(row1, column0) # 以下是rowl的其它按钮 Button(root, textDEL, width5, commandbackspace).grid(row1, column1) Button(root, text%, width5, commandlambda:show(%)).grid(row1, column2) Button(root, text/, width5, commandlambda:show(/)).grid(row1, column3) # 以下是row2的其它按钮 Button(root, text7, width5, commandlambda:show(7)).grid(row2, column0) Button(root, text8, width5, commandlambda:show(8)).grid(row2, column1) Button(root, text9, width5, commandlambda:show(9)).grid(row2, column2) Button(root, text*, width5, commandlambda:show(*)).grid(row2, column3) # 以下是row3的其它按钮 Button(root, text4, width5, commandlambda:show(4)).grid(row3, column0) Button(root, text5, width5, commandlambda:show(5)).grid(row3, column1) Button(root, text6, width5, commandlambda:show(6)).grid(row3, column2) Button(root, text-, width5, commandlambda:show(-)).grid(row3, column3) # 以下是row4的其它按钮 Button(root, text1, width5, commandlambda:show(1)).grid(row4, column0) Button(root, text2, width5, commandlambda:show(2)).grid(row4, column1) Button(root, text3, width5, commandlambda:show(3)).grid(row4, column2) Button(root, text, width5, commandlambda:show()).grid(row4, column3) # 以下是row5的其它按钮 Button(root, text0, width12, commandlambda:show(0)).grid(row5, column0, columnspan2) Button(root, text., width5, commandlambda:show(.)).grid(row5, column2) Button(root, text, width5, bgyellow, commandlambda:calculate()).grid(row5, column3) root.mainloop()运行结果