tkinter的特点
- 简单,相比其它GUI设计包,只有基本功能
- 内置于Python,跨平台
一般的程序架构
tk=tkinter.Tk()
tk.wm_title('中文标题')
label1=tkinter.Label(tk,text='Label')
label1['width']=20
label1['height']=4
label1['background']='red'
label1.pack()
tk.mainloop()
1. Tk()
创建一个新窗口对象
tk = tkinter.Tk()
tk.title("This is a title") # 窗口的标题
tk.geometry("400x200") # 窗口的默认大小,x是字母
tk.mainloop() # 时间循环
2. 控件属性
如示例程序,可以在生成控件时设定控件属性,也可以用类似dict的方法修改控件属性
通用的控件属性
- Dimensions:尺寸
- Colors:颜色
- Fonts:字体
- Anchor:锚(文本相对应位置参考点)
- nw, n, ne, w, center, e, sw, s, se
- Relief styles:浮雕式
- Bitmaps:显示位图
- Cursors:光标的外形
3. 界面布局
三种界面布局方式,pack, grid, place
3.1 pack()
tkinter.Button(tk, text="按钮上的文本", command=process_button1).\
pack(side="left")
默认从上往下排
有以下参数:(用这些参数做布局往往很复杂,建议不用)
- side:指定停靠在哪个方向,可以是’left’,’top’,’right’,’bottom’
- fill:’x’,’y’,’both’,’none’,表示填充方法:水平填充,竖直填充,双向填充,不填充
- expand:YES,NO
- anchor:(见于通用属性)
- ipadx:内边距的横方向
- ipady:内边距的竖直方向
- padx:外边距的横方向
- pady:外边距的竖直方向
3.2 grid()
可以把界面设置成数行数列,好处是无论如何拖动窗口,相对位置都不会变化
- row,column 从0开始的数,行数和列数
- rowspan, columnspan 从1开始的数,表表示跨越的行数或列数,默认是1
- stiky: 空间的对齐方式,’n’,’e’,’w’,’s’
- ipadx, ipady, padx, pady, x, y方向内外边距
import tkinter
tk=tkinter.Tk()
tkinter.Label(tk,text='姓名').grid(row=0,column=0,sticky='e')
tkinter.Entry(tk).grid(row=0,column=1,sticky='e')
tkinter.Label(tk,text='密码').grid(row=1,column=0,sticky='e')
tkinter.Entry(tk).grid(row=1,column=1,columnspan=1,sticky='w')
tkinter.Button(tk,text='登录').grid(row=2,column=1)
tkinter.Button(tk,text='清空').grid(row=0,column=2,rowspan=2,columnspan=1,)#,columnspan=2)
tk.mainloop()
3.3 place()
不是很推荐
4. 事件绑定
bind用于绑定事件,通用写法是:
窗体对象.bind(事件类型, 回调函数)
事件类型有以下几种:
'<Button-1>','<Button-2>','<Button-3>'
表示鼠标左中右键'<KeyPress-A>'
表示按下A键,A可以换成其它字母'<Control-V>'
表示按下ctrl+V,V可以换成其它字母'<F1>'
表示按下F1键
回调函数有一个输入,<ButtonPress event state=Mod1 num=1 x=111 y=21>
unbind(事件类型),解除绑定
bind_all()
5. 菜单
add_command
添加菜单项
import tkinter
tk=tkinter.Tk()
menubar=tkinter.Menu(tk)
tk['menu']=menubar
for i in ['文件','编辑','视图','关于']:
menubar.add_command(label=i)
tk.mainloop()
add_cascade级联
dict_mul={'文件':['新建','打开','保存','另存为'],
'编辑':['复制','黏贴','剪切'],
'视图':['默认视图','新式视图'],
'关于':['版权信息','其它说明']}
import tkinter
tk=tkinter.Tk()
menubar=tkinter.Menu(tk) # 总menu归属于tk
tk['menu']=menubar
for i in dict_mul:
temp=tkinter.Menu(menubar) # 子menu归属于menubar
menubar.add_cascade(label=i,menu=temp)
for j in dict_mul[i]:
temp.add_command(label=j)
tk.mainloop()
add_separator
插入一个横杠,与正常add_command一样,只是无需参数
15个常见控件
import tkinter
tk = tkinter.Tk()
tk.geometry("400x200")
# 这里填入控件
tk.mainloop()
通用属性
- bg/background:背景色,英文、RGB值
- fg/foreground: 前景色
Button()
tkinter.Button(tk,
text="按钮上的文本",
command=process_button1 # 按下按钮后调用的函数
, bg="#070", fg="#707" # 背景颜色,字体颜色
).grid()
- process_button1 是一个函数
- bitmap, compound, width, height, anchor, fg, bg, relief
额外
anchor:按钮上内容的位置[取值:n, ne, e, se, s, sw, w, nw, or center,其中n e s w是东南西北的缩写]
cursor:当鼠标移动到按钮上时所显示的光标【arrow:箭头,cross:十字,dot: 点,hand1:手 …….】
font:字体,使用元组来指定一个字体,这个元组包含了一个字体类型名字,一个以磅为单位的高度,代表一个或多个样式的字符串,比如("Times", 10, "bold")
background[可缩写为bg]:背景色,取值可未英文颜色字符串,或者RGB值
foreground[可缩写为fg]:前景色,取值可未英文颜色字符串,或者RGB值
borderwidth[可缩写为bd]::边框大小
activebackground:按钮处于活动状态时使用的背景颜色。
activeforeground:按钮处于活动状态时使用的前景颜色。
disabledforeground:禁用按钮时使用的颜色。
highlightbackground:当按钮没有焦点时用于高亮边框的颜色
relief:边框的装饰
列表里面是relief的可选值:["flat", "raised", "sunken", "solid", "ridge", "groove"]
flat是指按钮边框是平坦的,raise是指按钮边框是凸起的,sunken是指按钮边框是凹入的,solid是指按钮边框是粗边框…
按钮relief的效果:image
padx和pady:指定文本或图象与按钮边框的间距,x,y为x轴,y轴方向
height,widht:按钮的尺寸,height为高度,width为宽度,如果不设置则默认为包括文本内容
state:按钮的状态,可取值:NORMAL, ACTIVE 或 DISABLED。默认值为NORMAL。
justify:对齐方式
Canvas() 画布
可以在画布上插入文字、图形、图片、动画等
import tkinter
tk = tkinter.Tk()
tk.geometry("400x200")
canvas = tkinter.Canvas(tk, width=200, height=200)
canvas.grid()
canvas.create_text(180, 20, text="文字", fill="blue", font=("time", 16))
canvas.create_line((0, 0), (200, 200), width=8) # 起点坐标和终点坐标
canvas.create_polygon(10, 10, 100, 10, 100, 110, fill="", outline="black")
# 每两个数字构成一个点的坐标,然后依次画过去
# 下面是插入图
myImage = tkinter.PhotoImage(file="CSLO_logo.png")
canvas.create_image(10, 70, anchor=tkinter.NW, image=myImage)
canvas.pack()
# 下面是做动画
mytriangle = canvas.create_polygon(10, 10, 10, 60, 50, 35)
canvas.move(mytriangle, 5, 0)
canvas.itemconfig(mytriangle, fill='blue')
tk.mainloop()
Checkbutton:多选框
Entry():输入框
没有text这一属性
Label()
label = tkinter.Label(text='用户名:', # 文字
bitmap="error", # 图形
compound="center", # 图形在文字的那个位置,left, right, top, bottom, center
)
- 可以不要 bitmap,也可以不要 text,但如果两个都有,必须有compound
- bitmap可接收的属性(表示图形):
- error
- hourglass
- info
- questhead
- question
- warning
- gray12
- gray25
- gray50
- gray75
- bg,fg表示背景色和字体色
- width, height 表示宽度和高度
Listbox:列表框
Menubutton:菜单按钮
Menu:滚动条控件
当内容超过可视化区域时使用,如列表框。
Message
Radiobutton:单选框
Scale:范围控件
显示一个数值刻度,为输出限定范围的数字区间
Scrollbar
滚动条控件,当内容超过可视化区域时使用,如列表框。
Text:显示多行文本
Frame:框架
import tkinter
tk = tkinter.Tk()
tk.geometry("400x200")
frame = tkinter.Frame(tk, height=200, width=400, bg="black")
tkinter.Label(frame, text="label").grid() # 把frame当成个"子区域"使用
frame.grid()
tk.mainloop()
Toplevel:对话框
弹出一个对话框,用法和 Frame 类似
import tkinter
tk = tkinter.Tk()
tk.geometry("400x200")
top_level = tkinter.Toplevel(tk)
top_level.title("Top窗口")
top_level.geometry("100x100")
tkinter.Label(top_level, text="用户名:").pack()
tk.mainloop()
Spinbox:输入控件
与Entry类似,但是可以指定输入范围值
PanedWindow
PanedWindow是一个窗口布局管理的插件,可以包含一个或者多个子控件。
LabelFrame:labelframe
一个简单的容器控件。常用于复杂的窗口布局
tkMessageBox:用于显示你应用程序的消息框。
额外
“打开文件” 的对话框
tkinter.filedialog.asksaveasfilename():选择以什么文件名保存,返回文件名
tkinter.filedialog.asksaveasfile():选择以什么文件保存,创建文件并返回文件流对象
tkinter.filedialog.askopenfilename():选择打开什么文件,返回文件名
tkinter.filedialog.askopenfile():选择打开什么文件,返回IO流对象
tkinter.filedialog.askdirectory():选择目录,返回目录名
tkinter.filedialog.askopenfilenames():选择打开多个文件,以元组形式返回多个文件名
tkinter.filedialog.askopenfiles():选择打开多个文件,以列表形式返回多个IO流对象
实际案例
案例:改控件属性
import tkinter
tk = tkinter.Tk()
tk.geometry("400x200")
def process_button1():
button["text"] = "123" # 这样改控件的属性
button["fg"] = "blue"
button = tkinter.Button(text="button", bg="blue", command=process_button1)
button.grid()
tk.mainloop()
案例1:几张图以及用法
import tkinter
class CanvasDemo:
def __init__(self):
window = tkinter.Tk()
window.title("CanvasDemo")
self.canvas = tkinter.Canvas(window, width = 200, height = 100, bg = "White")
self.canvas.pack()
frame = tkinter.Frame(window)
frame.pack()
btRectangle = tkinter.Button(frame, text = "长方形", command = self.displayRect)
btOval = tkinter.Button(frame, text="椭 圆", command=self.displayOval)
btArc = tkinter.Button(frame, text = "圆 弧", command = self.displayArc)
btPolygon = tkinter.Button(frame, text="多边形", command=self.displayPolygon)
btLine = tkinter.Button(frame, text=" 线 ", command=self.displayLine)
btString = tkinter.Button(frame, text="文 字", command=self.displayString)
btClear = tkinter.Button(frame, text="清 空", command=self.clearCanvas)
btRectangle.grid(row = 1, column = 1)
btOval.grid(row=1, column=2)
btArc.grid(row=1, column=3)
btPolygon.grid(row=1, column=4)
btLine.grid(row=1, column=5)
btString.grid(row=1, column=6)
btClear.grid(row=1, column=7)
window.mainloop()
def displayRect(self):
self.canvas.create_rectangle(10, 10, 190, 90, tags = "rect")
def displayOval(self):
self.canvas.create_oval(10, 10, 190, 90, tags = "oval", fill = "red")
def displayArc(self):
self.canvas.create_arc(10, 10, 190, 90, start = 0, extent = 90, width = 8, fill = "red", tags = "arc")
def displayPolygon(self):
self.canvas.create_polygon(10, 10, 190, 90, 30, 50, tags = "polygon")
def displayLine(self):
self.canvas.create_line(10, 10, 190, 90, fill = 'red', tags = "line")
self.canvas.create_line(10, 90, 190, 10, width = 9, arrow = "last", activefill = "blue", tags = "line")
def displayString(self):
self.canvas.create_text(60, 40, text = "Hi,i am a string", font = "Tine 10 bold underline", tags = "string")
def clearCanvas(self):
self.canvas.delete("rect", "oval", "arc", "polygon", "line", "string")
CanvasDemo()
案例2:Menubar
import tkinter
class MenuDemo:
def __init__(self):
window = tkinter.Tk()
window.title("Menu demo")
menubar = tkinter.Menu(window,bg="red")
window.config(menu = menubar)
#创建下拉菜单,并添加到菜单条
operationMenu = tkinter.Menu(menubar, tearoff = 0)
menubar.add_cascade(label = "操作", menu = operationMenu)
operationMenu.add_command(label = "加", command = self.add)
operationMenu.add_command(label="减", command=self.subtract)
operationMenu.add_separator()
operationMenu.add_command(label = "乘", command = self.multiply)
operationMenu.add_command(label="除", command=self.divide)
exitMenu = tkinter.Menu(menubar, tearoff = 0)
menubar.add_cascade(label = "退出", menu = exitMenu)
exitMenu.add_command(label = "退出", command = window.quit)
tkinter.mainloop()
def add(self):
print("相加")
def subtract(self):
print("相减")
def multiply(self):
print("相乘")
def divide(self):
print("相除")
MenuDemo()
案例3:鼠标事件
import tkinter
class MenuDemo:
def __init__(self):
root = tkinter.Tk()
# create a popup menu
self.menu = tkinter.Menu(root, tearoff=0)
self.menu.add_command(label="Undo", command=self.hello)
self.menu.add_command(label="Redo", command=self.hello)
# create a canvas
self.frame = tkinter.Frame(root, width=512, height=512)
self.frame.pack()
# attach popup to canvas
self.frame.bind("<Button-1>", self.popup)
root.mainloop()
def popup(self, event):
self.menu.post(event.x_root, event.y_root)
def hello(self):
print("hello!")
MenuDemo()
详解:
widget.bind_all(event, handler)
- 其中event是一个字符串,表示所触发的事件
-
handler是一个函数,触发事件后调用这个函数
- event的值(字符串)与对应的描述
-
当拖拽小部件的时候 -
Button-1、Button-2、Button-3表示左键、中间键、右键点击 -
当释放鼠标的时候 -
当双击鼠标的时候 -
当鼠标光圈进入小部件的时候 -
当敲击一个键时候 -
-
当鼠标光圈离开小部件的时候 -
当敲击“Enter”键时候,可以将键盘任意一个键和一个事件绑定 - <Shift+A> 当敲击Shif+A的时候,可以和Alt、Control等组和
-
点击鼠标3次的时候
-
- handler函数的参数对应的属性
- char 从键盘输入的字符
- keycode 从键盘输入的键代码
- keysym 从键盘输入的键符号,”Up”,”Down”,”Left”,”Right”
- num 鼠标键的数字(1、2、3)
- widget 出发这个事件的小部件的对象
- x和y 当前鼠标在小部件的坐标(像素)
- x_root和y_root 当前鼠标相对于屏幕左上角的坐标(像素)
move
cvs.move(i,dx,dy)
- canvas上的第i个对象移动dx, dy
tkinter
from tkinter import *
import tkinter.simpledialog as dl
import tkinter.messagebox as mb
#tkinter GUI Input Output Example
#设置GUI
root = Tk()
w = Label(root, text = "Label Title")
w.pack()
#欢迎消息
mb.showinfo("Welcome", "Welcome Message")
guess = dl.askinteger("Number", "Enter a number")
output = 'This is output message'
mb.showinfo("Output: ", output)
参考资料
辛星tkinter教程第二版
https://www.cnblogs.com/progor/p/8505097.html