赞
踩
目录
6.灵活使用窗口update方法替换mainloop避免多线程或窗口after方法的使用
tkinter完整教程:Python tkinter(GUI编程)模块最完整教程(上)-CSDN博客
- ##Example1
- from tkinter import *
- parent = Tk()
- parent.title("parent")
-
- toplevel = Toplevel(parent)
- toplevel.title("toplevel")
- toplevel.transient(parent)#实现messagebox式的窗口
- mainloop()
- #这里需要注意的是,当父窗口隐藏后,经过transient简化的窗口也会跟随父窗口隐藏。
- ##Example2
- from tkinter import *
- root = Tk()
- root.title("Tk")
- toplevel = Toplevel(root)
- toplevel.title("Toplevel")
- root.attributes("-toolwindow", True)
- toplevel.attributes("-toolwindow", True)#实现menu点击虚线(tearoff)后的窗口效果
- mainloop()
- from tkinter import *
- parent = Tk()
- Toplevel(parent).overrideredirect(True)#实现隐藏了整个标题栏的窗口
- mainloop()
如果你要让整个窗口里的全部组件包括窗口都实现透明(可调节透明度),你可以使用Tk/Toplevel.attributes("-alpha",alphanum)参见:https://www.pynote.net/archives/1234
如果你要设置组件透明背景,实现字体透明,你可以使用Tk()/Toplevel().attributes("-transparentcolor",colorname)
需要注意的是,在Windows7中,透明的内容是无法被鼠标点击穿透的,用户不能点击透明区域的其他应用程序。但是在Windows10中,用户是可以的。而在其他系统中,可能无法执行transparentcolor。
- from tkinter import *
-
- root = Tk()
- root.attributes("-transparentcolor", "white")#此处将white颜色设置为透明,可以替换不同的颜色。
- Label(root, text="背景透明", bg="white").pack()#把已经变成透明色的白色设置为背景。
-
- mainloop()
- from tkinter import *
- root = Tk()
- root.bell()#系统提示音
在做应用的时候,在用户操作失败时可以设定执行bell方法。
tkinter的组件通常是一起绘制到窗口上面的,如果想要让一部分的绘制等待,就可以使用wait_window(),wait_visibility()和wait_variable()方法。使用这两种方法,可以使部分代码变简便。
比如在程序中,弹出一个对话框,等用户输入后按下确定,然后继续操作。这样的程序就必须使用wait_系列方法,等用户输入完后根据wait绑定的内容继续程序,否则无法直接操作用户的输入内容。
这时我们可以利用wait_系列方法:
这样就可以直接用if句式,使代码简洁。
- from tkinter import *
-
- root = Tk()
- root.wait_window(root)
- print("root已经被销毁")
-
- #mainloop()
- #mainloop不需要执行,因为这一段执行到时root已经被销毁
在上面这段代码中,wait_window后面的内容不会被执行,但是当用户点下窗口的关闭按钮销毁窗口,才会打印后面的"root已经被销毁"。
- from tkinter import *
-
- root = Tk()
- var = StringVar()
- Button(root, text="改变var", command=lambda:var.set("change")).pack()
- root.wait_variable(var)
- print("var的内容出现了改变")
-
- mainloop()
在这一段代码中,只有当var的内容有了变化,才会停止阻塞,执行后面的print函数。用户点击Button时,将var的内容设置为"change",wait_variable检测到了内容改变,将后面的代码运行完毕,打印内容。因为这并不是一个事件,所以后面的代码只能运行一次。
- from tkinter import *
-
- root = Tk()
- label = Label(root, text="")
- Button(root, text="改变label的可见性", command=label.pack).pack()
- root.wait_visibility(label)
- print("label的可见性被改变!")
-
- mainloop()
这一段代码中,当按下了Button,将label的可见性改变(如隐藏、放置) ,wait_visibility停止,执行后面的print代码。
在使用wait系列方法的时候,代码会自动进入主循环,你不需要考虑mainloop写在前面还是后面。
下面看一个示例,演示了wait_variable的使用。
- from tkinter import *
-
- root = Tk()
- root.title("判断")
- result = Variable(value=None)
-
- Label(root, text="请问1+1=2是否正确?").pack()
-
- Button(root, text="正确", command=lambda: result.set(True)).pack()
- Button(root, text="错误", command=lambda: result.set(False)).pack()
-
- root.wait_variable(result) #阻塞下面的进程,直到root.result改变
- root.destroy() #在没有选择之前,这一段会一直阻塞
-
- if result.get():
- print("你答对了")
- else:
- print("你答错了")
在tkinter中,最常用的方法就是在程序末尾执行mainloop,可以用来反复刷新窗口。如果想在刷新窗口的同时进行某些操作,但是不想用麻烦的after或多线程,就可以直接用while True循环代替。
mainloop()其实也是一个while True循环,下面两段代码是等价的:
- from tkinter import *
-
- #1
- root = Tk()
- root.mainloop()
-
- #2
- root = Tk()
- while True:
- root.update()
比如我要不断打印用户在Entry里面的输入内容,可以使用mainloop,如下:
- from tkinter import *
-
- root = Tk()
- entry = Entry(root)
- entry.pack()
-
- def print_entry():
- print(entry.get())
- root.after(0, print_entry)
-
- root.after(0, print_entry)
- mainloop()
但如果用while True: root.update() ,可以写作这样:
- from tkinter import *
-
- root = Tk()
- entry = Entry(root)
- entry.pack()
-
- def print_entry():
- print(entry.get())
-
- while True:
- root.update()
- print_entry()
这样不但简单了很多,而且逻辑也十分清楚,也不必考虑取消after之类的复杂问题。
- root = Tk()
- root.attributes("-disable", True)
设置为True后窗口将被禁用,无法激活也无法拖拽,无法在上面操作。 设置为False可以取消禁用。
tk可以使窗口或组件处于“忙碌”状态。处于忙碌状态的组件不能进行任何操作,并且鼠标在上面时显示为加载样式(watch)。
tkinter暂不支持通过方法设置组件的忙碌状态,只能调用Tcl命令。
- from tkinter import *
-
- root = Tk()
- b = Button(root, text="BUTTON")
- b.pack()
-
- root.tk.call("tk", "busy", "hold", b) #设置为忙碌状态
-
- mainloop()
忙碌状态下的组件并没有改变颜色、字体等样式。
如果要取消忙碌状态,可以使用如下命令:
root.tk.call("tk", "busy", "forget", widget)
也可以设置忙碌状态下的鼠标样式,即:
root.tk.call("tk", "busy", "configure", widget, "-cursor", cursorname)
关于更多可以参考Tcl/Tk文档。
Tk8.6新增了字体选择对话框,用于对字体的选择。tkinter没有方法能够实现字体选择,只能通过调用Tcl命令。
显示字体选择对话框,可以使用如下命令:
root.tk.call("tk", "fontchooser", "show")
但是,这个方法并不会返回字体选择的结果,所以在显示之前,需要进行设置。可以传递一个回调函数用于处理字体的选择结果。这个回调函数必须注册为Tcl的函数才能实现功能。
- def font_changed(font):
- print("选择字体的结果:", font)
-
- root.tk.call("tk", "fontchooser", "configure", "-font", "helvetica 24", "-command", root.register(font_changed))
主题是定义应用程序组件外观样式的集合,主题不同的组件样式不相同。
要想在组件上应用窗口主题,需要使用ttk的组件。先需定义ttk.Style()。
s = ttk.Style()
theme_names()方法返回所有的内置主题以及在系统上还可以应用的主题。
s.theme_names()
theme_use方法返回当前使用的主题。也可以用theme_use方法设置当前窗口的主题。
如图是内置主题以及效果。
以上发现的相关内容大都来源于tkinter(Tcl/Tk)的源码研究,很多内容,也可以从tkinter源码中找到答案。
tkinter完整教程:Python tkinter(GUI编程)模块最完整教程(上)-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。