tkinter库
python自带的库
import tkinter
或 from tkinter import *
查看tkinter版本
tkinter.TkVersion
import tkinter
print(tkinter.TkVersion)
窗口设置
方法汇总与示例
方法 | 说明 | 示例 |
---|---|---|
title(str) | 窗口标题 | title(‘such_test’) |
geometry(‘widthxheight+x+y’) | 窗口宽高、位置。 width:窗口宽度,height:窗口高度;x:以左上角为原点;距离左边的距离;y:以左上角为原点;距离上边的距离; | geometry(‘800x600+300+150’) |
root = Tk()
root.title('such_test') # 窗口标题
root.geometry('800x600+300+150') # 窗口宽高、位置
root.configure(bg='#4682B4') # 窗口背景色
root.mainloop() # 建立
居中显示
通过获取屏幕宽高,计算出位置。
root = Tk()
root.title('such_test') # 窗口标题
width = 800
height = 600
screen_width = root.winfo_screenwidth() # 获取屏幕宽
screen_height = root.winfo_screenheight() # 获取屏幕高
x = (screen_width - width) / 2
y = (screen_height - height) / 2
root.geometry('%dx%d+%d+%d' % (width, height, x, y)) # 窗口宽高、位置
root.configure(bg='#4682B4') # 窗口背景色
root.mainloop() # 建立
窗口拖拽时的大小设置
def get_screen_size():
"""获取屏幕宽高"""
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
return screen_width, screen_height
if __name__ == '__main__':
root = Tk()
root.title('such_test') # 窗口标题
width = 800
height = 600
x, y = get_center_location(width, height)
root.geometry('%dx%d+%d+%d' % (width, height, x, y)) # 窗口宽高、位置
root.configure(bg='#4682B4') # 窗口背景色
# root.resizable(0, 0) # 窗口不可更改大小
root.maxsize(*get_screen_size()) # 设置窗口拖拽时的最大大小
root.minsize(400, 200) # 设置窗口拖拽时的最小大小
root.mainloop() # 建立
控件(Widget)
汇总
模块包含的控件
tkinter的加强版是tkinter.ttk(简称ttk)
控件 | 模块 |
---|---|
Button | tkinter、ttk |
Checkbutton | tkinter、ttk |
Entry | tkinter、ttk |
Frame | tkinter、ttk |
Label | tkinter、ttk |
LabelFrame | tkinter、ttk |
MenuButton | tkinter、ttk |
Radiobutton | tkinter、ttk |
Scale | tkinter、ttk |
Scrollbar | tkinter、ttk |
PanedWindow | tkinter、ttk |
Combobox | ttk |
Notebook | ttk |
Progressbar | ttk |
Separator | ttk |
sizegrip | ttk |
Treeview | ttk |
控件的共同属性
名称 | 说明 | 示例 |
---|---|---|
dimensions | 大小 | |
colors | 颜色 | |
fonts | 字体 | |
anchor | 锚(位置参考点)。可设置值:nw,n,ne,w,cneter,e,sw,s,se | anchor=‘nw’ |
relief styles | 属性边框 。可设置值:flat,groove,raised,ridge,solid,sunken | relief=‘raised’ |
bitmaps | 显示位图 | |
cursors | 鼠标外形 |
anchor的各位置示意:
w cneter e
sw s se
控件的共同方法
名称 | 说明 | 示例 |
---|---|---|
config(option=value) | 属性设置 | |
cget(‘option’) | 获取属性设置值 | |
keys() | 获取控制的所有参数 | |
mainloop() | 让程序继续执行,进入等待与处理窗口事件 | |
quit | 窗口结束。但是所建窗口继续执行 | |
bind(event,callback) | 事件绑定 | |
unbind(event) | 解除事件绑定 |
控件配置管理员
名称 | 说明 | 示例 |
---|---|---|
pack(option=value) | ||
grid() | ||
place() |
pack
参数名称 | 说明 | 示例 |
---|---|---|
side | 排列方式。可选值 :TOP,BOTTOM,LEFT,RIGHT | label.pack(side=LEFT) |
padx | 控件边界与容器的x轴间距 | |
pady | 控件边界与容器的y轴间距 | |
ipadx | 标签文字与容器的x轴间距 | |
ipady | 标签文字与容器的y轴间距 | |
anchor | 控件在容器中的位置 | |
fill | 控件填满所分配容器区间的方式。可选值:X,Y,BOTH。默认是None | |
expand | 控件是否填满额外的父容器空间。可选值:True,False。默认False |
label
label(master,option)
master:容器。即在哪个窗口中建立该控件。
option:(dict)属性-值字典。
label的anchor默认是center,即上下左右都居中对齐。
root = Tk()
root.title('such_test') # 窗口标题
width = 800
height = 600
x, y = get_center_location(width, height)
root.geometry('%dx%d+%d+%d' % (width, height, x, y)) # 窗口宽高、位置
bg_color = '#39889f'
root.configure(bg=bg_color) # 窗口背景色
# root.resizable(0, 0) # 窗口不可更改大小
root.maxsize(*get_screen_size()) # 设置窗口拖拽时的最大大小
min_width = 400
root.minsize(400, 200) # 设置窗口拖拽时的最小大小
options = {
'text': '你好!',
'font': '楷体',
'fg': '#cee1e7',
'bg': bg_color,
'wraplength': min_width,
}
label = Label(root, options)
label.pack() # 包装与定位控件
root.mainloop()
标签内图像
方式一:
PhotoImage(file=filepath)
image = PhotoImage(file='static/image/logo.png')
options = win.set_label_common('SUCH TEST')
options['anchor'] = 'nw'
label = Label(root, options, image=image,compound='left')
label.pack() # 包装与定位控件
方式二:
使用pillow模块,先安装:pip install pillow
from PIL import Image,ImageTk
image = Image.open('static/image/logo.png')
stone=ImageTk.PhotoImage(image)
options = win.set_label_common('SUCH TEST')
options['anchor'] = 'nw'
label = Label(root, options, image=stone,compound='left') # compound使图像与文字共存
label.pack() # 包装与定位控件
效果:
button
此处开始,为了方便布局,均把pack()改用成grid()了。
# 关闭
options = {'width': 5}
btn = Button(root, text='关闭', **options,command=root.quit)
btn.grid(row=1, column=3,
) # 包装与定位控件
entry文本框
Entry(master,option=value)
show参数可以设定输入时的显示内容,不设置show参数时,默认输入什么就显示什么。
options = win.set_label_common('用户名')
label = Label(root, options)
label.grid(row=3, column=2) # 包装与定位控件
label = Entry(root)
label.grid(row=3, column=3) # 包装与定位控件
options = win.set_label_common('密码')
label = Label(root, options)
label.grid(row=4, column=2) # 包装与定位控件
label = Entry(root,show='*')
label.grid(row=4, column=3) # 包装与定位控件
options = {'width': 20}
btn = Button(root, text='登录', **options)
btn.grid(row=5, column=2, columnspan=2) # 包装与定位控件
输入效果如下:
canvas(画布)
创建画布
绘制线条
绘制实线
from tkinter import *
root = Tk()
# 画布
width = 800
height = 600
canvas = Canvas(root, width=width, height=height)
canvas.pack()
# 绘制实线
canvas.create_line(10, 10, 100, 100, fill='red')
root.mainloop()
绘制虚线
create_line()方法中通过dash参数设置虚线。dash=(实线像素1,虚线像素1,实线像素2,虚线像素2,…)
例如:create_line(60, 100, 60, 200, dash=(3, 1))
Windows和Linux下的效果不一致,要理解dash参数如何绘制,参考linux下的效果。
from tkinter import *
root = Tk()
# 画布
width = 800
height = 600
canvas = Canvas(root, width=width, height=height)
canvas.pack()
# 绘制实线
canvas.create_line(10, 10, 100, 100, fill='red')
# 绘制虚线
canvas.create_line(60, 100, 60, 200, dash=(3, 1))
canvas.create_line(70, 100, 70, 200, dash=(5, 1))
canvas.create_line(80, 100, 80, 200, dash=(3, 1, 1))
canvas.create_line(90, 100, 90, 200, dash=(3, 1, 1, 1))
canvas.create_line(100, 100, 100, 200, dash=(5, 2, 2, 2))
canvas.create_line(110, 100, 110, 200, dash=(5, 2, 2, 2, 2, 2))
root.mainloop()
Windows下的效果:
绘制圆或椭圆
create_oval(x1, y1, x2, y2)
(为了方便,以下的圆形均是指圆或椭圆)
x1,y1是圆形所在方形左上角的点坐标,x2,y2是圆形所在方形右下角的点坐标。
通过x1y1,x2y2得到的方形,再绘制出与该方形四条边均相切于中点的圆形。故绘制出来的圆形的形状,取决于x1y1,x2y2绘制出的方形是什么样的形状。
x1y1,x2y2得到的是正方形,那绘制出来的是圆,如果是长方形则绘制出来的是椭圆。
为了方便理解,下面代码画圆的时候,把方形也用虚线绘制出来了。
from tkinter import *
root = Tk()
# 画布
width = 800
height = 600
canvas = Canvas(root, width=width, height=height)
canvas.pack()
# 绘制圆
x1=150
y1=150
x2=300
y2=300
canvas.create_line(x1,y1,x1,y2, dash=(3, 1))
canvas.create_line(x1,y1,x2,y1, dash=(3, 1))
canvas.create_line(x2,y1,x2,y2, dash=(3, 1))
canvas.create_line(x1,y2,x2,y2, dash=(3, 1))
canvas.create_oval(x1, y1, x2, y2, outline='blue')
# 绘制椭圆
x1=360
y1=360
x2=450
y2=500
canvas.create_line(x1,y1,x1,y2, dash=(3, 1))
canvas.create_line(x1,y1,x2,y1, dash=(3, 1))
canvas.create_line(x2,y1,x2,y2, dash=(3, 1))
canvas.create_line(x1,y2,x2,y2, dash=(3, 1))
canvas.create_oval(x1, y1, x2, y2, outline='blue')
root.mainloop()
来个图形小实例:
import math
from tkinter import *
def get_screen_size(root):
"""获取屏幕宽高"""
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
return screen_width, screen_height
def get_center_location(root, width, height):
"""获取屏幕居中位置"""
screen_width, screen_height = get_screen_size(root)
return (screen_width - width) / 2, (screen_height - height) / 2
width = 800
height = 600
bg_color = '#39889f'
min_width = 400
min_height = 200
# 新建窗口
root = Tk()
root.title('such_test') # 窗口标题
x, y = get_center_location(root, width, height)
root.geometry('%dx%d+%d+%d' % (width, height, x, y)) # 窗口宽高、位置
root.configure(bg=bg_color) # 窗口背景色
root.maxsize(*get_screen_size(root)) # 设置窗口拖拽时的最大大小
root.minsize(min_width, min_height) # 设置窗口拖拽时的最小大小
# root.overrideredirect(True) # 去掉边框
root.config(cursor='heart')
# 画布
canvas = Canvas(root, width=width, height=height)
canvas.create_rectangle(0, 0, width, height, outline=None, fill=bg_color)
canvas.create_rectangle(0, 0, width, height, outline=None, activefill='skyblue', activestipple="gray50")
canvas.pack()
# 画
r = 100
between = (height - 4 * r) / 3 # 去掉两圆直径外的空白距离三等分,得到上中下间距
# 第一个连线圆
x_center = width / 2 # 圆心的x坐标
y_center = between + r # 圆心的y坐标
x_li = []
y_li = []
for i in range(12):
x_li.append(x_center + r * math.sin(30 * i * math.pi / 180))
y_li.append(y_center + r * math.cos(30 * i * math.pi / 180))
for i in range(12):
for j in range(12):
canvas.create_line(x_li[i], y_li[i], x_li[j], y_li[j], fill='white')
# 第二个圆中连线
r = 100
x_center = width / 2 # 圆心的x坐标
y_center = 2 * between + 3 * r # 圆心的y坐标
# 圆周
x1 = x_center - r
y1 = y_center - r
x2 = x_center + r
y2 = y_center + r
canvas.create_oval(x1, y1, x2, y2, outline='white')
x_li = []
y_li = []
for i in range(12):
x_li.append(x_center + r * math.sin(30 * i * math.pi / 180))
y_li.append(y_center + r * math.cos(30 * i * math.pi / 180))
for i in range(12):
for j in range(12):
if math.fabs(i - j) != 1:
canvas.create_line(x_li[i], y_li[i], x_li[j], y_li[j], fill='white')
root.mainloop()
动画
移动
canvas.move(obj_id,xMove,yMove) # 移动对象
tk.update() # 强制重绘
obj_id是移动对象,xMove是移动的x轴距离,yMove是移动的y轴距离。
from time import sleep
from tkinter import *
root = Tk()
# 画布
width = 800
height = 600
canvas = Canvas(root, width=width, height=height)
canvas.pack()
# 绘制圆
x1=150
y1=150
x2=300
y2=300
canvas.create_line(x1,y1,x1,y2, dash=(3, 1))
canvas.create_line(x1,y1,x2,y1, dash=(3, 1))
canvas.create_line(x2,y1,x2,y2, dash=(3, 1))
canvas.create_line(x1,y2,x2,y2, dash=(3, 1))
oval_id=canvas.create_oval(x1, y1, x2, y2, outline='blue')
for x in range(0,50):
canvas.move(oval_id,5,0)
root.update()
sleep(0.05)
root.mainloop()
前面【绘制贺或椭圆】的小实例,将两个图案均进行移动:
import math
from time import sleep
from tkinter import *
def get_screen_size(root):
"""获取屏幕宽高"""
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
return screen_width, screen_height
def get_center_location(root, width, height):
"""获取屏幕居中位置"""
screen_width, screen_height = get_screen_size(root)
return (screen_width - width) / 2, (screen_height - height) / 2
width = 800
height = 600
bg_color = '#39889f'
min_width = 400
min_height = 200
# 新建窗口
root = Tk()
root.title('such_test') # 窗口标题
x, y = get_center_location(root, width, height)
root.geometry('%dx%d+%d+%d' % (width, height, x, y)) # 窗口宽高、位置
root.configure(bg=bg_color) # 窗口背景色
root.maxsize(*get_screen_size(root)) # 设置窗口拖拽时的最大大小
root.minsize(min_width, min_height) # 设置窗口拖拽时的最小大小
# root.overrideredirect(True) # 去掉边框
root.config(cursor='heart')
# 画布
canvas = Canvas(root, width=width, height=height)
canvas.create_rectangle(0, 0, width, height, outline=None, fill=bg_color)
canvas.create_rectangle(0, 0, width, height, outline=None, activefill='skyblue', activestipple="gray50")
canvas.pack()
# 虚线
# canvas.create_line(60, 100, 60, 200, dash=(3, 1))
# canvas.create_line(70, 100, 70, 200, dash=(5, 1))
# canvas.create_line(80, 100, 80, 200, dash=(3, 1, 1))
# canvas.create_line(90, 100, 90, 200, dash=(3, 1, 1, 1))
# canvas.create_line(100, 100, 100, 200, dash=(5, 2, 2, 2))
# canvas.create_line(110, 100, 110, 200, dash=(5, 2, 2, 2, 2, 2))
# 画
r = 50
between = (height - 4 * r) / 3
# 第一个连线圆
x_center = width / 2
y_center = between + r
x_li = []
y_li = []
obj_ids1=[] # 将绘制对象存起来
for i in range(12):
x_li.append(x_center + r * math.sin(30 * i * math.pi / 180))
y_li.append(y_center + r * math.cos(30 * i * math.pi / 180))
for i in range(12):
for j in range(12):
obj_ids1.append(canvas.create_line(x_li[i], y_li[i], x_li[j], y_li[j], fill='white'))
# 第二个圆中连线
x_center = width / 2
y_center = 2 * between + 3 * r
# 圆周
x1 = x_center - r
y1 = y_center - r
x2 = x_center + r
y2 = y_center + r
obj_ids=[] # 将绘制对象存起来
obj_ids.append(canvas.create_oval(x1, y1, x2, y2, outline='white'))
x_li = []
y_li = []
for i in range(12):
x_li.append(x_center + r * math.sin(30 * i * math.pi / 180))
y_li.append(y_center + r * math.cos(30 * i * math.pi / 180))
for i in range(12):
for j in range(12):
if math.fabs(i - j) != 1:
obj_ids.append(canvas.create_line(x_li[i], y_li[i], x_li[j], y_li[j], fill='white'))
for x in range(0,50):
# 第一个图形移动
for obj in obj_ids1:
canvas.move(obj,5,0)
# 第二个圆移动
for obj in obj_ids:
canvas.move(obj,5,0)
root.update()
sleep(0.05)
root.mainloop()
没有录制动图,只有一张静图: