Python tkinter一些十分灵活的运用方式和实用函数

目录

1.隐藏窗口最大化和最小化按钮

2.隐藏整个标题栏

3.实现组件透明背景和透明字体

4.发出系统提示音

5.等待输出(wait_window()等方法)

6.灵活使用窗口update方法替换mainloop避免多线程或窗口after方法的使用

7.禁用窗口

8.使组件处于busy状态

9.调用字体选择对话框

10.窗口主题


1.隐藏窗口最大化和最小化按钮

##Example1
from tkinter import *
parent = Tk()
parent.title("parent")

toplevel = Toplevel(parent)
toplevel.title("toplevel")
toplevel.transient(parent)#实现messagebox式的窗口
mainloop()
​#这里需要注意的是,当父窗口隐藏后,经过transient简化的窗口也会跟随父窗口隐藏。

Python tkinter一些十分灵活的运用方式和实用函数_第1张图片

##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()

Python tkinter一些十分灵活的运用方式和实用函数_第2张图片

2.隐藏整个标题栏

from tkinter import *
parent = Tk()
Toplevel(parent).overrideredirect(True)#实现隐藏了整个标题栏的窗口
mainloop()

Python tkinter一些十分灵活的运用方式和实用函数_第3张图片

3.实现组件透明背景和透明字体

如果你要让整个窗口里的全部组件包括窗口都实现透明(可调节透明度),你可以使用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()

Python tkinter一些十分灵活的运用方式和实用函数_第4张图片

4.发出系统提示音

from tkinter import *
root = Tk()
root.bell()#系统提示音

在做应用的时候,在用户操作失败时可以设定执行bell方法。

5.等待输出(wait_window()等方法)

tkinter的组件通常是一起绘制到窗口上面的,如果想要让一部分的绘制等待,就可以使用wait_window(),wait_visibility()和wait_variable()方法。使用这两种方法,可以使部分代码变简便。

比如在程序中,弹出一个对话框,等用户输入后按下确定,然后继续操作。这样的程序就必须使用wait_系列方法,等用户输入完后根据wait绑定的内容继续程序,否则无法直接操作用户的输入内容。

这时我们可以利用wait_系列方法:

  • Tk/Toplevel.wait_window(window=None):表示阻塞后面执行的内容,等后面的window组件销毁后才执行。
  • Tk/Toplevel.wait_visibility(window=None):表示阻塞后面的内容,等window的可见性改变后才执行后面的内容。
  • Tk/Toplevel.wait_variable(name="PY_VAR"):表示阻塞后面的内容,直到name(是一个PY_VAR,比如String Var,Int Var)

这样就可以直接用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("你答错了")

6.灵活使用窗口update方法替换mainloop避免多线程或窗口after方法的使用

在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之类的复杂问题。

7.禁用窗口

root = Tk()
root.attributes("-disable", True)

设置为True后窗口将被禁用,无法激活也无法拖拽,无法在上面操作。 设置为False可以取消禁用。

8.使组件处于busy状态

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文档。

9.调用字体选择对话框

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))

10.窗口主题

主题是定义应用程序组件外观样式的集合,主题不同的组件样式不相同。

要想在组件上应用窗口主题,需要使用ttk的组件。先需定义ttk.Style()。

s = ttk.Style()

theme_names()方法返回所有的内置主题以及在系统上还可以应用的主题。

s.theme_names()

theme_use方法返回当前使用的主题。也可以用theme_use方法设置当前窗口的主题。

 Python tkinter一些十分灵活的运用方式和实用函数_第5张图片

如图是内置主题以及效果。

以上发现的相关内容大都来源于tkinter(Tcl/Tk)的源码研究,很多内容,也可以从tkinter源码中找到答案。

你可能感兴趣的:(Python,tkinter,python)