过程式风格的Tkinter教程展示了如何使用过程式编程风格在Tkinter中创建简单的GUI应用程序。Tkinter教程中使用了面向对象的编程风格-OOP风格。
Tkinter
Tkinter是一个绑定到TkGUI工具包的Python。Tk是Tcl语言的原始GUI库。Tkinter是作为Python包装器实现的,它围绕着嵌入Python中的完整Tcl解释器。
Tkinter是Python标准安装的一部分。
Tkinter退出按钮
Button
小部件是用于执行操作的标准Tkinter小部件。
#!/usr/bin/python import tkinter root = tkinter.Tk() root.title('Quit button') btn = tkinter.Button(root, text="Quit", width=8, command=root.quit) btn.pack(pady=10) root.geometry("300x250+300+300") root.mainloop()
该示例创建了一个退出按钮。单击按钮时,应用程序终止。
import tkinter
我们导入tkinter
模块。
root = tkinter.Tk()
一个根窗口被创建。根窗口是我们应用程序中的主应用程序窗口。它有一个标题栏和边框。这些由窗口管理器提供。根窗口必须在任何其他小部件之前创建。
root.title('Quit button')
使用title
方法,我们设置窗口的标题。
btn = tkinter.Button(root, text="Quit", width=8, command=root.quit)
Button
小部件已创建。按钮构造函数的第一个参数是父控件;它是根窗口。text
参数指定按钮的标签。width
设置按钮的宽度。command
参数指定单击按钮时执行的函数。root.quit
终止应用程序。
btn.pack(pady=10)
pack
是Tkinter中的三个布局管理器之一。它将按钮放在父级上并显示它。pady
在按钮上方和下方放置了一些空间。
root.geometry("300x250+300+300")
geometry
方法设置窗口的大小并将其定位在屏幕上。前两个参数是窗口的宽度和高度。最后两个参数是x和y屏幕坐标。
root.mainloop()
最后,我们进入主循环。主循环从窗口系统接收事件并将它们分派给应用程序小部件。当我们点击标题栏的关闭按钮或调用quit
方法时,它就终止了。
Tkinter中心窗口
通过geometry
方法,我们将应用程序窗口置于屏幕中心。
#!/usr/bin/python import tkinter root = tkinter.Tk() root.title('Centered window') win_width = 300 win_height = 250 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() start_x = int((screen_width/2) - (win_width/2)) start_y = int((screen_height/2) - (win_height/2)) root.geometry('{}x{}+{}+{}'.format(win_width, win_height, start_x, start_y)) root.mainloop()
为了使窗口在屏幕上居中,我们需要知道屏幕和窗口的尺寸。
win_width = 300 win_height = 250
这是窗口的宽度和高度。
screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight()
我们使用winfo_screenwidth
和winfo_screenheight
方法获取屏幕的宽度和高度。
start_x = int((screen_width/2) - (win_width/2)) start_y = int((screen_height/2) - (win_height/2))
我们计算窗口左上角的x和y坐标。
root.geometry('{}x{}+{}+{}'.format(win_width, win_height, start_x, start_y))
我们用geometry
将窗口放置在屏幕上。
Tkinter检查按钮
Checkbutton
是一个有两种状态的小部件:打开和关闭。打开状态由复选标记可视化。
Checkbutton
与变量关联。变量存储按钮的当前状态(打开或关闭)。
#!/usr/bin/python import tkinter def toggleTitle(): isTitleShown = cbvar.get() if isTitleShown: root.title('Checkbutton example') else: root.title('') root = tkinter.Tk() root.title('Checkbutton example') cbvar = tkinter.BooleanVar() cbtn = tkinter.Checkbutton(root, text="Show", width=8, variable=cbvar, command=toggleTitle) cbtn.select() cbtn.pack(pady=10) root.geometry("300x250+300+300") root.mainloop()
Checkbutton
位于窗口上。它显示或隐藏窗口的标题。
def toggleTitle(): isTitleShown = cbvar.get() if isTitleShown: root.title('Checkbutton example') else: root.title('')
toggleTitle
函数切换窗口的标题。我们从关联的cbvar
获取Checkbutton
的状态。根据其状态,我们使用title
显示或隐藏标题。
cbvar = tkinter.BooleanVar()
创建了一个BooleanVar
。
cbtn = tkinter.Checkbutton(root, text="Show", width=8, variable=cbvar, command=toggleTitle)
创建了一个Checkbutton
。variable
参数设置关联变量。command
参数确定在选择或取消选择Checkbutton
时调用的函数。
Tkinter标签
Label
是一个可以显示文本或图像的标准小部件。
为了处理图像,我们需要安装pillow
模块。
$ pip3 install pillow
我们使用pip
安装模块。
#!/usr/bin/python import tkinter from PIL import Image, ImageTk root = tkinter.Tk() root.configure(background='gray') root.title("Rotunda") rot_i = Image.open("rotunda.jpg") rotunda = ImageTk.PhotoImage(rot_i) label = tkinter.Label(image=rotunda) label.image = rotunda label.place(x=20, y=20) root.mainloop()
我们的示例显示JPG图像。
from PIL import Image, ImageTk
Label
小部件只能显示一组有限的图像类型。要显示JPG图像,我们必须使用PIL,即Python图像库模块。通过Pillow教程了解有关PIL的更多信息。
root.configure(background='gray')
我们通过configure
将主窗口的背景颜色更改为灰色。
rot_i = Image.open("rotunda.jpg")
我们从位于当前工作目录中的图像文件创建一个Image
。
rotunda = ImageTk.PhotoImage(rot_i)
根据图像创建照片图像。
label = tkinter.Label(image=rotunda)
照片图像被赋予标签小部件的图像参数。
label.image = rotunda
必须存储图像引用,以免图像被垃圾收集。
label.place(x=20, y=20)
我们使用place
方法使用绝对坐标将图像放置在窗口上。
Tkinter消息框
消息框是一个显示警告、错误或信息的小对话窗口。
#!/usr/bin/python import tkinter import tkinter.messagebox import datetime def showDate(): now = datetime.datetime.now() msg = 'Today is: {}'.format(now) tkinter.messagebox.showinfo("Information", msg) root = tkinter.Tk() root.title('Message box') btn = tkinter.Button(root, text="Show date", padx=5, pady=5, width=10, command=showDate) btn.pack(pady=10) root.geometry('300x300+300+250') root.mainloop()
在这个例子中,我们展示了一个信息消息框。单击按钮时会显示该框。
import tkinter.messagebox
调用消息框的方法在tkinter.message
模块中。
def showDate(): now = datetime.datetime.now() msg = 'Today is: {}'.format(now) tkinter.messagebox.showinfo("Information", msg)
showDate
方法显示消息框。对话窗口显示当前日期和时间。tkinter.messagebox.showinfo
显示信息消息框。
btn = tkinter.Button(root, text="Show date", padx=5, pady=5, width=10, command=showDate)
点击按钮showDate
方法被调用。
Tkinter菜单
菜单栏是位于各种菜单中的一组命令。我们可以在应用程序中使用的菜单组命令。
#!/usr/bin/python import tkinter import tkinter.messagebox import datetime def showDay(): now = datetime.datetime.now() msg = 'Today is: {}'.format(now.strftime('%A')) tkinter.messagebox.showinfo("Information", msg) root = tkinter.Tk() root.title('Menu') menubar = tkinter.Menu(root) root.config(menu=menubar) fileMenu = tkinter.Menu(menubar) fileMenu.add_command(label="Show day", command=showDay) fileMenu.add_command(label="Exit", command=root.quit) menubar.add_cascade(label="File", menu=fileMenu) root.geometry('300x200+300+250') root.mainloop()
该示例创建了一个包含两个选项的文件菜单:显示日期和退出。
def showDay(): now = datetime.datetime.now() msg = 'Today is: {}'.format(now.strftime('%A')) tkinter.messagebox.showinfo("Information", msg)
showDay
显示一个显示当前日期的对话框。
menubar = tkinter.Menu(root) root.config(menu=menubar)
创建了一个菜单栏。它是一个常规的菜单小部件,配置为根窗口的菜单栏。
fileMenu = tkinter.Menu(menubar)
一个文件菜单对象被创建。菜单是包含命令的下拉窗口。
fileMenu.add_command(label="Show day", command=showDay) fileMenu.add_command(label="Exit", command=root.quit)
我们使用add_command
方法添加两个选项。command
属性指定在选择菜单选项时要调用的函数。
menubar.add_cascade(label="File", menu=fileMenu)
使用add_cascade
方法,将文件菜单添加到菜单栏。
Tkinter弹出菜单
弹出菜单,也称为上下文菜单,是一种可以显示在窗口客户区任意位置的菜单。
#!/usr/bin/python import tkinter import tkinter.messagebox import datetime def showDay(): now = datetime.datetime.now() msg = 'Today is: {}'.format(now.strftime('%A')) tkinter.messagebox.showinfo("Information", msg) def showMenu(e): pmenu.post(e.x_root, e.y_root) root = tkinter.Tk() root.title('popup menu') pmenu = tkinter.Menu(root, tearoff=0) pmenu.add_command(label="Show day", command=showDay) pmenu.add_command(label="Exit", command=root.quit) root.bind("<Button-3>", showMenu) root.geometry('300x250+300+250') root.mainloop()
在示例中,我们创建了一个包含两个命令的弹出菜单。
pmenu = tkinter.Menu(root, tearoff=0)
上下文菜单是一个常规的菜单小部件。tearoff
功能已关闭。现在无法将菜单分离到新的顶层窗口中。
root.bind("<Button-3>", showMenu)
我们将事件类型绑定到
showMenu
调用。当我们右键单击窗口的客户区时会生成该事件。
def showMenu(e): pmenu.post(e.x_root, e.y_root)
showMenu
方法显示上下文菜单。弹出菜单显示在鼠标单击的x
和y
坐标处。
Tkinter包布局管理器
pack几何管理器将小部件打包成行或列。我们可以使用fill
、expand
、padx
、pady
和side
等选项>控制布局。
#!/usr/bin/python import tkinter root = tkinter.Tk() root.title('Pack layout') lbl1 = tkinter.Label(root, width=20, height=5, bg='SteelBlue2') lbl1.pack(side=tkinter.LEFT, padx=10, pady=10) lbl2 = tkinter.Label(root, width=20, height=5, bg='SteelBlue3') lbl2.pack(side=tkinter.LEFT) lbl3 = tkinter.Label(root, width=20, height=5, bg='SteelBlue4') lbl3.pack(side=tkinter.LEFT, padx=10) root.geometry('+300+250') root.mainloop()
在这个例子中,我们将三个标签排成一行。
lbl1.pack(side=tkinter.LEFT, padx=10, pady=10)
使用side
选项,我们将小部件打包成一行。padx
添加了一些水平空间。pady
添加了一些垂直空间。
在第二个示例中,我们将小部件放入一列。
#!/usr/bin/python import tkinter root = tkinter.Tk() root.title('Pack layout') lbl1 = tkinter.Label(root, width=20, height=5, bg='SlateGray2') lbl1.pack(side=tkinter.TOP, pady=15, padx=10) lbl2 = tkinter.Label(root, width=20, height=5, bg='SlateGray3') lbl2.pack(side=tkinter.TOP, padx=10) lbl3 = tkinter.Label(root, width=20, height=5, bg='SlateGray4') lbl3.pack(side=tkinter.TOP, pady=15, padx=10) root.geometry('+300+250') root.mainloop()
该示例将三个标签放入一列。
lbl1.pack(side=tkinter.TOP, pady=15, padx=10)
为了将标签放入列中,我们将side
选项设置为tkinter.TOP
。
在第三个示例中,我们使用包管理器创建一行标签和一列标签。
#!/usr/bin/python import tkinter root = tkinter.Tk() root.title('Pack layout') frame1 = tkinter.LabelFrame(root, text='Vertical layout', relief=tkinter.GROOVE) lbl1 = tkinter.Label(frame1, width=15, height=3, bg='SlateGray2') lbl1.pack(side=tkinter.TOP, pady=15, padx=10) lbl2 = tkinter.Label(frame1, width=15, height=3, bg='SlateGray3') lbl2.pack(side=tkinter.TOP, padx=10) lbl3 = tkinter.Label(frame1, width=15, height=3, bg='SlateGray4') lbl3.pack(side=tkinter.TOP, pady=15, padx=10) frame1.pack(pady=10) frame2 = tkinter.LabelFrame(root, text='Horizontal layout', relief=tkinter.GROOVE) lbl4 = tkinter.Label(frame2, width=15, height=3, bg='SkyBlue2') lbl4.pack(side=tkinter.LEFT, pady=15, padx=10) lbl5 = tkinter.Label(frame2, width=15, height=3, bg='SkyBlue3') lbl5.pack(side=tkinter.LEFT, padx=10) lbl6 = tkinter.Label(frame2, width=15, height=3, bg='SkyBlue4') lbl6.pack(side=tkinter.LEFT, pady=15, padx=10) frame2.pack(padx=10, pady=10) root.geometry('+300+250') root.mainloop()
我们创建了两个LabelFrame
小部件。这些将包含标签。框架本身被打包成一列。
frame1 = tkinter.LabelFrame(root, text='Vertical layout', relief=tkinter.GROOVE) lbl1 = tkinter.Label(frame1, width=15, height=3, bg='SlateGray2') lbl1.pack(side=tkinter.TOP, pady=15, padx=10) lbl2 = tkinter.Label(frame1, width=15, height=3, bg='SlateGray3') lbl2.pack(side=tkinter.TOP, padx=10) lbl3 = tkinter.Label(frame1, width=15, height=3, bg='SlateGray4') lbl3.pack(side=tkinter.TOP, pady=15, padx=10) frame1.pack(pady=10)
第一个LabelFrame
包含一列三个标签。
frame2 = tkinter.LabelFrame(root, text='Horizontal layout', relief=tkinter.GROOVE) lbl4 = tkinter.Label(frame2, width=15, height=3, bg='SkyBlue2') lbl4.pack(side=tkinter.LEFT, pady=15, padx=10) lbl5 = tkinter.Label(frame2, width=15, height=3, bg='SkyBlue3') lbl5.pack(side=tkinter.LEFT, padx=10) lbl6 = tkinter.Label(frame2, width=15, height=3, bg='SkyBlue4') lbl6.pack(side=tkinter.LEFT, pady=15, padx=10) frame2.pack(padx=10, pady=10)
第二个LabelFrame
包含一行三个标签。
Tkinter网格布局管理器
网格布局管理器在二维网格中组织其子项。网格由列和行组成。列和行的交叉点称为单元格。
#!/usr/bin/python import tkinter root = tkinter.Tk() root.title('Grid') root.columnconfigure(0, pad=5) root.columnconfigure(1, pad=5) root.columnconfigure(2, pad=5) root.rowconfigure(0, pad=5) btn1 = tkinter.Button(root, text='Button 1') btn1.grid(column=0, row=0) btn2 = tkinter.Button(root, text='Button 2') btn2.grid(column=1, row=0) btn3 = tkinter.Button(root, text='Button 3') btn3.grid(column=2, row=0) btn4 = tkinter.Button(root, text='Button 4') btn4.grid(column=0, row=1) btn5 = tkinter.Button(root, text='Button 5') btn5.grid(column=1, row=1) btn6 = tkinter.Button(root, text='Button 6') btn6.grid(column=2, row=1) root.geometry('300x300+300+250') root.mainloop()
在示例中,我们将六个按钮放置在一个网格中。
root.columnconfigure(0, pad=5) root.columnconfigure(1, pad=5) root.columnconfigure(2, pad=5) root.rowconfigure(0, pad=5)
使用columnconfigure
和rowconfigure
方法,我们在行和列之间添加了一些空间。
btn1.grid(column=0, row=0)
grid
方法将小部件放入网格中。column
和row
属性指定单元格的索引。此按钮位于网格左上角的单元格中。
Tkinter比例
“比例”小部件允许用户通过沿比例移动旋钮来选择数值。我们可以控制最小值和最大值以及分辨率。
#!/usr/bin/python import tkinter def onScale(val): v = int(val) lvar.set(v) root = tkinter.Tk() root.title('Scale example') root.columnconfigure(0, pad=5) root.columnconfigure(1, pad=15) root.rowconfigure(0, pad=5) scale = tkinter.Scale(root, from_=0, to=100, orient=tkinter.HORIZONTAL, command=onScale) scale.grid(column=0, row=0) lvar = tkinter.IntVar() label = tkinter.Label(root, text=0, textvariable=lvar) label.grid(column=1, row=0) root.geometry("300x220+300+300") root.mainloop()
在代码示例中,我们有一个Scale
和一个Label
。使用Scale选择的值显示在相邻的Label
中。布局是使用网格管理器创建的。
def onScale(val): v = int(val) lvar.set(v)
onScale
方法在我们移动Scale的旋钮时被调用。我们获取刻度的当前值并将其设置为标签的关联变量。
scale = tkinter.Scale(root, from_=0, to=100, orient=tkinter.HORIZONTAL, command=onScale)
Scale
小部件已创建。我们指定初始值和结束值、方向和回调函数。
lvar = tkinter.IntVar() label = tkinter.Label(root, text=0, textvariable=lvar)
这是显示比例尺选定值的标签。
Tkinter按键事件
当用户按下键盘键时会产生按键事件。我们使用bind
方法将事件类型映射到事件处理程序。按键事件的事件类型是。
#!/usr/bin/python import tkinter def onKeyPress(e): msg = 'Key {}, (code {}) was pressed'.format(e.keysym, e.keycode) lvar.set(msg) root = tkinter.Tk() root.title('Key event') lvar = tkinter.StringVar() lbl = tkinter.Label(root, text="coordinates", textvariable=lvar) lbl.place(x=20, y=20) root.bind('<Key>', onKeyPress) root.geometry("300x250+300+300") root.mainloop()
在示例中,我们在标签小部件中显示了按下键的键事件属性。
def onKeyPress(e): msg = 'Key {}, (code {}) was pressed'.format(e.keysym, e.keycode) lvar.set(msg)
onKeyPress
是按键事件的事件处理程序。我们在标签小部件中显示按键符号和按键代码。
root.bind('<Key>', onKeyPress)
我们将事件类型绑定到
onKeyPress
事件处理程序。
Tkinter鼠标移动事件
鼠标移动事件的事件类型是。
#!/usr/bin/python import tkinter def onMotion(e): msg = 'x: {} y: {}'.format(e.x, e.y) lvar.set(msg) root = tkinter.Tk() root.title('Mouse move event') lvar = tkinter.StringVar() lbl = tkinter.Label(root, text="coordinates", textvariable=lvar) lbl.place(x=20, y=20) root.bind('<Motion>', onMotion) root.geometry("300x250+300+300") root.mainloop()
该示例显示了当前鼠标指针在labelwidget中的坐标。
def onMotion(e): msg = 'x: {} y: {}'.format(e.x, e.y) lvar.set(msg)
在onMotion
回调中,我们获取鼠标指针的x和y坐标,形成一条文本消息并将其设置为标签的关联变量。
root.bind('<Motion>', onMotion)
我们将事件类型绑定到
onMotion
回调。
Tkinter跳转按钮
以下示例是一个使用事件类型的小型预告片应用程序。enter事件在用户使用鼠标指针进入小部件时生成。
#!/usr/bin/python import tkinter import random def onEnterButton(e): w = root.winfo_width() h = root.winfo_height() b_w = btn.winfo_width() b_h = btn.winfo_height() r_x = random.randrange(0, w - b_w) r_y = random.randrange(0, h - b_h) btn.place(x=r_x, y=r_y) root = tkinter.Tk() root.title('Jumping button') root.resizable(False, False) btn = tkinter.Button(root, text='Exit', width=10, command=root.quit) btn.place(x=180, y=20) btn.bind('<Enter>', onEnterButton) root.geometry("600x600+30+30") root.mainloop()
用户试图点击按钮,这应该会终止应用程序。按钮通过从鼠标指针处随机跳转来逃避点击。
def onEnterButton(e): w = root.winfo_width() h = root.winfo_height() b_w = btn.winfo_width() b_h = btn.winfo_height() r_x = random.randrange(0, w - b_w) r_y = random.randrange(0, h - b_h) btn.place(x=r_x, y=r_y)
onEnterButton
函数在用户进入按钮区域时被调用。我们确定根窗口和按钮的尺寸。然后我们使用这些值在窗口区域随机重新定位按钮。按钮通过使用绝对坐标的place
方法显示。
root.resizable(False, False)
我们不允许窗口调整大小,这让用户更难接受。
btn = tkinter.Button(root, text='Exit', width=10, command=root.quit)
按钮的command
属性设置为root的quit
方法。如果用户设法单击按钮,则窗口终止。
btn.bind('<Enter>', onEnterButton)
我们将事件类型绑定到
onEnterButton
回调。
Tkinter画布颜色
Tkinter中的绘图是在Canvas
小部件上完成的。Canvas
是在Tkinter中进行图形处理的高级工具。
#!/usr/bin/python import tkinter root = tkinter.Tk() root.title('Canvas colours') canvas = tkinter.Canvas(root) canvas.create_rectangle(30, 10, 120, 80, outline="#fb0", fill="#fb0") canvas.create_rectangle(150, 10, 240, 80, outline="#f50", fill="#f50") canvas.create_rectangle(270, 10, 370, 80, outline="#05f", fill="#05f") canvas.pack(fill=tkinter.BOTH, expand=1) root.geometry("400x100+300+300") root.mainloop()
该示例显示了三个填充了三种不同颜色的矩形。
canvas = tkinter.Canvas(root)
创建了Canvas
小部件。
canvas.create_rectangle(30, 10, 120, 80, outline="#fb0", fill="#fb0")
使用create_rectangle
方法创建矩形。前四个参数是两个边界点的x
和y
坐标:左上角和右下角点。通过outline
参数,我们可以控制矩形轮廓的颜色。同样,fill
参数为矩形内部提供颜色。
在本教程中,我们使用过程式编程在Python中使用Tkinter创建了GUI应用程序。ZetCode上提供了一本独特的电子书Tkinter编程;PDF格式,包含200页和89个代码示例。
列出Python教程。