再简单的产品,运用了GUI就会显得具有较高的完成度。Tkinter是自带的GUI库,使用起来比较方便,基本的功能也可以实现,够用了。Tkinter官方文档非常全面,但是有的功能用的比较少,所以这里按照John E. Greyson所著的《Python and Tkinter Programming》中的顺序来学习,书中的版本比较旧,在遇到具体问题时,参阅了官方文档。
1 Tkinter控件
介绍Tkinter模块和它与Tcl/Tk的关系。
1.1 Toplevel窗口类
Toplevel控件为其他控件提供独立的容器,如框架。教材上把root主窗口和toplevel窗口统称为Toplevel对象了。有的教材上会对两者加以区别,Tk()创建的称为主窗口,是唯一的。Toplevel创建的称为Toplevel窗口,是可以分层次的。简单来讲,对于单窗口的应用程序,当你初始化Tk时创建的toplevel对象root,就可以为你提供所需的一切。共有四种toplevel。
root主窗口
就是主程序的窗口,关闭这个窗口,程序终止。使用root = Tk()初始化tk时,就会自动生成root。
child子窗口
以root为master创建Toplevel对象,即创建了root的子窗口。事实上,任意一级窗口都可以作为master创建子窗口。子窗口相对独立于其所依赖的master主窗口存在,当主窗口销毁时,child窗口才销毁。子窗口只吃关闭。
transient暂态窗口
创建方法与子窗口相同,创建好子窗口后,调用handler.transient(root)方法,将子窗口设置为暂态窗口。暂态窗口与主窗口保持高度同步,它本身没有最小化按钮,随主窗口最小化、恢复或关闭。暂态窗口吃一切。
undecorated无边框窗口
创建方法与子窗口相同,创建好子窗口后,调用handler.overrideredirect(True)方法,将子窗口设置为无边框窗口。无框窗口同子窗口,只吃关闭。
另外,只有toplevel对象可以调用geometry方法,设置窗口大小。
from tkinter import *
root = Tk()
#root.option_readfile('option_DB')
root.title('Toplevel')
Label(root, text='This is the main (default) Toplevel').pack(pady=10)
t1 = Toplevel(root)
Label(t1, text='This is a child of root').pack(padx=10, pady=10)
t2 = Toplevel(root)
Label(t2, text='This is a transient window of root').pack(padx=10, pady=10)
t2.transient(root)
t3 = Toplevel(t1, borderwidth=5, bg='blue')
Label(t3, text='No wm decorations', bg='blue', fg='white').pack(padx=10, pady=10)
t3.overrideredirect(True)
t3.geometry('200x70+150+150')
root.mainloop()
1.2 Frame框架
Frame为toplevel窗口中的其他控件提供区域容器。frame除了标准的控件选项之外,几乎没有其他方法可用。frame最常用的功能,就是讲一组其他控件打包,并用几何管理工具一并处理。
初始化frame实例时,主要传入master和属性字。master就是所在toplevel的句柄。常用的属性字主要有2个。
一是浮雕效果(relief=‘xxx’),共有六种:平面(flat)、凸面(raised)、凹面(sunken)、凸框(ridge)、凹框(groove)、实线框(solid)。
二是框线宽度(borderwidth=x)。x是像素数,一定要设,否则frame什么都不显示(与flat效果相同)。
import tkinter as tk
root = tk.Tk()
root.title('Frame Example')
frm = tk.Frame(root, relief='solid', borderwidth=1, width=300, height=150)
frm1 = tk.Frame(frm, relief='groove', borderwidth=2)
lb1 = tk.Label(frm1, text='You shot him!').pack(pady=10)
btn1 = tk.Button(frm1, text="He's dead!").pack(side='left', padx=5, pady=8)
btn2 = tk.Button(frm1, text="He's completely dead!").pack(side='right', padx=5, pady=8)
frm1.place(anchor='nw', relx=0.01, rely=0.1)
lb2 = tk.Label(frm, text='Self-defence against fruit', bg='blue')
lb2.place(anchor='w', relx=0.05, rely=0.125)
frm.pack()
root.mainloop()
这里初步接触了一下几何方法place,可以说这个小例子完全是关于place的用法的,关于几何管理的内容我们等学习后面的内容时再接触。
第一层框架是frm, 它的master是root,它的大小是定值宽300像素,高150像素。实际上可以只设置这两个属性,这样frm框架便不会显示出来。为了明显起见,这里将框线设为实线了。
第一层框架下有一个控件(label控件lb2)和一个框架(frm1)。
初识placer
关于place的用法,重点在于理解anchor的用法。在一个大矩形中准确地定义一个小矩形(有面积,不是点)的位置,需要知道三个信息:一是坐标系定义,二是坐标数据,三是要在小矩形上指定一个定位点。
原点和坐标系完全是系统默认的定义方式,即原点在master控件的左上角,向右向下为正。
坐标数据以相对形式给出,取0到1之间的浮点数。如果取0,则参考点横坐标为0(在最左侧),如果取1,则参考点横坐标为master控件的最右侧,纵坐标也是如此。
如图,定义位置时,以master控件的左上角为原点,以给定的相对坐标(这里都是0.5)指定位置。每个控件都有9个anchor,选一个作为“把手”,将这个“把手”安放在指定位置即可。anchor='nw’的含义是“将控件的左上角安放在指定位置”。再如:
anchor='n’的含义是“将控件的上边中点安放在指定位置”。其他的anchor同理。这也就是为什么正规的python代码中,默认先设置指定坐标,最后再选择anchor。