一、基本概念
python3默认的UI工具包是tkinter.
顶层窗口: 包含具体窗口内容的容器是顶层窗口;
控件:顶层窗口上可以包含一些小的窗口组件,称之为控件;
根窗口: GUI程序可以有多个顶层窗口,但只能有一个顶层窗口是根窗口。
控件可以独立存在,也可以作为容器存在。
包含其它控件的控件被称为那些控件的父控件,而被包含的控件叫做该控件的子控件;
一个GUI程序从开始到结束是通过整套事件体系来驱动的,这种方式称为事件驱动处理;
tkinter有三种布局管理器来帮助控件集进行定位:Place,Pack,Grid;
当所有控件都摆好之后,程序就可以进入无限的主循环之中,所有其它的行为都通过回调来处理。
二、pack布局
因为UI暂时不是我学习的重点,因此这里仅记录pack布局方式。
更多内容可参考:
http://effbot.org/tkinterbook/tkinter-index.htm
pack布局管理器在行和列上对控件进行组织。你可以使用的选项包括:fill, expand, and side。
何时使用pack布局:
- 将一个控件填满其父容器控件
- 将数个控件纵向排列
- 将数个控件横向排列
示例1:
from tkinter import *
root = Tk()
listbox = Listbox(root)
listbox.pack()
for i in range(20):
listbox.insert(END, str(i))
mainloop()
默认显示,20个数字只显示出来10个,此时我们会去拖动窗口,让窗口尺寸变大。
尺寸改变之后,listbox的大小并未改变,显示效果不好:
改进如下:
listbox.pack(fill=BOTH, expand=1)
我们给pack方法给了两个参数,那么listbox的尺寸就会跟随父控件的尺寸而变化了:
示例2:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
' a test module '
__author__ = 'TaoGuan'
from tkinter import *
root = Tk()
w = Label(root, text="Red", bg="red", fg="white")
w.pack()
w = Label(root, text="Green", bg="green", fg="black")
w.pack()
w = Label(root, text="Blue", bg="blue", fg="white")
w.pack()
mainloop()
可以使用fill=X,让子控件与父控件等宽:
from tkinter import *
root = Tk()
w = Label(root, text="Red", bg="red", fg="white")
w.pack(fill=X)
w = Label(root, text="Green", bg="green", fg="black")
w.pack(fill=X)
w = Label(root, text="Blue", bg="blue", fg="white")
w.pack(fill=X)
mainloop()
示例3
from tkinter import *
root = Tk()
w = Label(root, text="Red", bg="red", fg="white")
w.pack(side=LEFT)
w = Label(root, text="Green", bg="green", fg="black")
w.pack(side=LEFT)
w = Label(root, text="Blue", bg="blue", fg="white")
w.pack(side=LEFT)
mainloop()
三、常用控件演示
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
' Lable and Button'
__author__ = 'TaoGuan'
import tkinter as tk
import tkinter.messagebox
from PIL import Image, ImageTk
class APP():
def __init__(self, master):
# 加载图标
self.icon = Image.open('test.ico')
self.icon = ImageTk.PhotoImage(self.icon)
# 窗口标题
master.title('测试窗口')
# 窗口主菜单
self.setupMainMenus(master)
# 创建frame
self.frame = tk.Frame(master)
self.frame.pack()
# Label
self.setupLabels(self.frame)
# Button
self.setupButtons(self.frame)
# CheckButton
self.setupCheckButtons(self.frame)
# RadioButton
self.setupRadioButtons(self.frame)
# Entry
self.setupInputBox(self.frame)
# Message
self.setupMessages(self.frame)
# Canvas
self.setupCanvases(self.frame)
# 鼠标事件
self.mouseEventsSetup(self.frame)
# 键盘事件
self.keyEventsSetup(self.frame)
# 弹出提示信息
def callback(self):
tkinter.messagebox.showinfo('提示','人生苦短, 我用python!')
# 构造主菜单
def setupMainMenus(self, master):
mainmenu = tk.Menu(master)
master.config(menu=mainmenu)
filemenu = tk.Menu(mainmenu)
mainmenu.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="New", command=self.callback)
filemenu.add_command(label="Open...", command=self.callback)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=self.callback)
helpmenu = tk.Menu(mainmenu)
mainmenu.add_cascade(label="Help", menu=helpmenu)
helpmenu.add_command(label="About...", command=self.callback)
def setupButtons(self, master):
frame1 = tk.Frame(master)
frame1.pack()
# button除了能显示文字和图像外,还可以跟用户产生交互,执行指定的动作
tk.Button(frame1, text='我是普通按钮,点我', command=self.callback).pack(anchor=tk.W)
tk.Button(frame1, text="我是图文按钮,点我", image=self.icon, compound=tk.RIGHT, command=self.callback).pack(anchor=tk.W)
tk.Button(frame1, text='我是被禁用的按钮,点我没反应', command=self.callback, state=tk.DISABLED).pack(anchor=tk.W)
mb = tk.Menubutton(frame1, text='菜单按钮')
mb.pack(anchor=tk.W)
filemenu = tk.Menu(mb)
filemenu.add_command(label='打开', command=self.callback)
filemenu.add_command(label='保存', command=self.callback)
filemenu.add_command(label='退出', command=root.quit)
mb.config(menu=filemenu)
def setupLabels(self, master):
frame1 = tk.Frame(master)
frame1.pack()
# label用来显示一些描述性的信息,比如显示文字和图像
tk.Label(frame1,text='我是一个普通Label').pack(anchor=tk.W)
tk.Label(frame1, text='我是一个图文Label', image=self.icon, compound=tk.RIGHT).pack(anchor=tk.W)
def setupCheckButtons(self, master):
frame1 = tk.Frame(master)
frame1.pack()
ck1 = tk.Checkbutton(frame1, text='boy')
ck1.select()
ck1.pack(anchor=tk.W)
tk.Checkbutton(frame1, text='girl').pack(anchor=tk.W)
def setupRadioButtons(self, master):
frame1 = tk.Frame(master)
frame1.pack()
frame2 = tk.Frame(master)
frame2.pack()
MODES = [
("Monochrome", "1"),
("Grayscale", "L"),
("True color", "RGB"),
("Color separation", "CMYK"),
]
v1 = tk.StringVar()
v2 = tk.StringVar()
v1.set("L") # initialize
v2.set("1") # initialize
for text, mode in MODES:
b = tk.Radiobutton(frame1, text=text,
variable=v1, value=mode, indicatoron=1)
b.pack(anchor=tk.W)
for text, mode in MODES:
b = tk.Radiobutton(frame2, text=text,
variable=v2, value=mode, indicatoron=0)
b.pack(anchor=tk.W)
def setupInputBox(self, master):
frame1 = tk.Frame(master)
frame1.pack()
self.e = tk.Entry(frame1)
self.e.pack()
#self.e.focus_set()
tk.Button(frame1, text='点我', command=self.showInputText).pack(anchor=tk.W)
def showInputText(self):
tkinter.messagebox.showinfo('提示',self.e.get())
def setupMessages(self, master):
frame1 = tk.Frame(master)
frame1.pack()
tk.Message(frame1, text="this is a message").pack(anchor=tk.W)
tk.Message(frame1, text="this is a relatively long message", width=50).pack(anchor=tk.W)
def setupCanvases(self, master):
frame1 = tk.Frame(master)
frame1.pack()
ww = tk.Canvas(frame1, width=200, height=100)
ww.pack()
ww.create_line(0, 0, 200, 100)
ww.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
ww.create_rectangle(50, 25, 150, 75, fill="blue")
def mouseEventsSetup(self, master):
frame1 = tk.Frame(master)
frame1.pack()
self.clrIndex1 = 0
lab = tk.Label(frame1, text='我会变色,我现在是绿色', bg = 'green')
lab.pack(anchor=tk.W)
lab.bind("<Enter>", self.mouseEnterCallBack)# 鼠标进入控件
def keyEventsSetup(self, master):
frame1 = tk.Frame(master)
frame1.pack()
self.labchar = tk.Label(frame1, text='char:', bg = 'red')
self.labchar.pack(anchor=tk.W)
self.labkeycode= tk.Label(frame1, text='keycode:', bg = 'yellow')
self.labkeycode.pack(anchor=tk.W)
self.labkeysym = tk.Label(frame1, text='keysym:', bg = 'green')
self.labkeysym.pack(anchor=tk.W)
self.labtype = tk.Label(frame1, text='type:', bg='pink')
self.labtype.pack(anchor=tk.W)
self.frame.bind('<Key>',self.keyboardCallBack)
self.frame.focus_set()
def mouseEnterCallBack(self, event):
if self.clrIndex1== 0:
event.widget['background']='red'
event.widget['text']='我会变色,我现在是红色'
self.clrIndex1=1
else:
event.widget['background']='green'
event.widget['text']='我会变色,我现在是绿色'
self.clrIndex1=0
def keyboardCallBack(self, event):
self.labchar['text'] = 'char:' + event.char
self.labkeycode['text']= 'keycode:' + str(event.keycode)
self.labkeysym['text']='keysym:' + str(event.keysym)
self.labtype['text']='type:' + str(event.type)
# 创建root窗口
root = tk.Tk()
# 创建app对象
app = APP(root)
# 进入主循环
root.mainloop()