文章目录
- 前言
- 常见问题
- 组件使用示例
- 1、简单实例
- 2、Label控件
- 3、Button控件
- 4、Entry控件
- 5、点击按钮输出输入框中的内容
- 6、Text控件
- 7、带滚动条的Text
- 8、Radiobutton圆圈单选框
- 9、Checkbutton方形多选框控件
- 10、Listbox控件一
- 11、Listbox控件二
- 12、Scale控件
- 13、Spinbox控件(上下箭头选择数值)
- 14、Menu顶层菜单
- 15、Menu鼠标右键菜单
- 16、Combobox下拉选项控件
- 17、messagebox弹出窗口
- 18、弹出窗口接收数据
- 19、Notebook选项卡标签(很好玩)
- 20、分割控件
- 21、Frame控件
- 21、表格数据(Treeview)
- 22、树状数据
- 23、组件的鼠标点击事件
- 24、组件的鼠标移动事件
- 25、组件的鼠标释放事件
- 26、进入和离开事件
- 27、响应所有按键的事件
- 28、响应特殊按键事件
- 29、指定按键事件
- 30、组合按键事件
- 综合案例
前言
Tkinter模块(“Tk 接口”)是Python的标准Tk GUI工具包的接口,
Tk和Tkinter可以在大多数的Unix平台下使用,同样可以应用在Windows和Macintosh系统里,
Tk8.0的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。
上手简单,适合新手入手GUI编程
本博客诸多内容参考自:https://www.cnblogs.com/yudanqu/p/9467803.html
常见问题
设置窗口大小不可变
window.resizable(width=False, height=False)# 窗口大小不可改变
设置组件不可用
btn1.state(['disabled'])
btn1.state(['!disabled'])
btn1['state'] = DISABLED ###禁用
btn1['state'] = NORMAL
好看的字体
font=('Microsoft YaHei', 10)
好看的颜色
在线查看颜色:https://encycolorpedia.cn/html
颜色参看:https://blog.csdn.net/chl0000/article/details/7657887
Entry如何插入或删除数据
import tkinter as tk
win = tk.Tk()
# e输入框显示字符串:木芙蓉
def _show():
e.insert(0, '木芙蓉')
# 清空e输入框中的内容
def _clear():
e.delete(0, tk.END)
var = tk.StringVar()
e = tk.Entry(win, textvariable=var)
e.pack()
b_show = tk.Button(win, text='显示木芙蓉', command=_show)
b_show.pack()
b_clear = tk.Button(win, text='清空', command=_clear)
b_clear.pack()
win.mainloop()
Text如何插入或删除数据
获取Text文本内容:text.get('0.0','end')
该方式表示获取text中现有的全部内容;
设置Text文本内容:
text.insert('end',s):该方法是将s插入到text的末尾,原来的内容不变;
text.insert('insert',s);该方法是将s插入到鼠标点击的地方;
text.insert(1.1, var) #表示在第一行第一位显示
删除Text文本内容:
text.delete('1.0','end'):该方法是将text文本内的内容全部清空。
三种布局方式布局方式
全局只能使用一种方式,笔者喜欢place
详情参考:https://blog.csdn.net/diaoweisang7683/article/details/101968216
绝对布局place
绝对布局(绝对布局,窗口的变化对位置没有影响)
label1.place(x=10,y=10)
相对布局pack
相对布局,窗体改变对控件有影响
label2.pack(fill=tkinter.X, side=tkinter.TOP)
表格布局grid
label.grid(row=1,column=1)
如何放置图片
import tkinter as tk
window = Tkinter.Tk()
image_file1 = tk.PhotoImage(file='./data/bg5.png')
l1=tk.Label(window,image=image_file1)
l1.place(x=-2,y=0)
window.mainloop()
如何询问文件路径
from tkinter.filedialog import askopenfilename
filename = askopenfilename()
print(filename)
如何修改label、button的text
label['text'] = '修改后'
设置界面初始的桌面位置
这里的100、200,表示相对于桌面的x=100,y=200
window.geometry("400x400+100+200")
面向对象设计GUI
import tkinter as tk
from tkinter import ttk
class Program(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
container.grid_rowconfigure(2, weight=1)
container.grid_columnconfigure(2, weight=1)
self.frames = {}
frame = Login(container, self)
self.frames[Login] = frame
frame.grid(row=1, column=1, sticky="nsew")
for F in (Login, AdminHome):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row = 1, column = 1, sticky = "nsew")
self.show_frame(Login)
def show_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class Login(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
name = tk.Label(self, text = "Program")
name.grid(row=0, columnspan=5, sticky="W"+"E")
username = tk.Label(self, text="Username: ")
username.grid(row=1, columnspan=2, sticky="W")
user = ttk.Entry(self, text ="", width=45)
user.grid(row=1, column=2 ,columnspan=3, sticky="w")
password = tk.Label(self, text="Password: ")
password.grid(row=2, columnspan=2, sticky="W")
passentry = ttk.Entry(self, text ="", width=45)
passentry.grid(row=2, column=2 ,columnspan=3, sticky="W")
loginb = ttk.Button(self, text = "Login", command = lambda: controller.show_frame(AdminHome))
loginb.grid(row=3, columnspan=5, sticky="W"+"E")
class AdminHome(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
name = tk.Label(self, text = "Admin Home")
name.grid(row=0, sticky="W")
name = tk.Label(self, text = "FirstName + LastName")
name.grid(row=0, column=5 ,sticky="E")
update = ttk.Button(self, text = "Update Online", command = lambda: controller.show_frame(AdminHome))
update.grid(row=1, columnspan=6, sticky="W"+"E")
fetch = ttk.Button(self, text = "Fetch Data", command = lambda: controller.show_frame(AdminHome))
fetch.grid(row=2, columnspan=6, sticky="W"+"E")
a = ttk.Button(self, text = "a", command = lambda: controller.show_frame(AdminHome))
a.grid(row=3, columnspan=2, sticky="W"+"E")
b = ttk.Button(self, text = "b", command = lambda: controller.show_frame(AdminHome))
b.grid(row=3, column=2, columnspan=2, sticky="W"+"E")
c = ttk.Button(self, text = "c", command = lambda: controller.show_frame(AdminHome))
c.grid(row=3, column=4, columnspan=2, sticky="W"+"E")
edit = ttk.Button(self, text = "Edit Details", command = lambda: controller.show_frame(AdminHome))
edit.grid(row=4, columnspan=6, sticky="W"+"E")
app = Program()
app.state('zoomed')
app.mainloop()
组件使用示例
1、简单实例
下面的代码是创建出一个窗口,其他的操作就在这个平台上进行。执行之后会在桌面弹出一个窗口,窗口的标题就是代码中设置的win.title。
import tkinter
# 创建主窗口
win = tkinter.Tk()
# 设置标题
win.title("yudanqu")
# 设置大小和位置
win.geometry("400x400+200+50")
# 进入消息循环,可以写控件
win.mainloop()
2、Label控件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
'''
Label:标签控件,可以显示文本
'''
# win:父窗体
# text:显示的文本内容
# bg:背景色
# fg:字体颜色
# font:字体
# wraplength:指定text文本中多宽之后换行
# justify:设置换行后的对齐方式
# anchor:位置 n北,e东,w西,s南,center居中;还可以写在一起:ne东北方向
# 属性relief为控件呈现的3D浮雕样式,有FLAT(平的)、RAISED(凸起的)、SUNKEN(凹陷的)、GROOVE(沟槽状边缘)和RIDGE(脊状边缘)5种。
# must be flat, groove, raised, ridge, solid, or sunken
label = tkinter.Label(win,
text="this is a word",
bg="pink", fg="red",
font=("黑体", 20),
width=20,
height=10,
wraplength=100,
justify="left",
anchor="ne")
# 显示出来
label.pack()
win.mainloop()
3、Button控件
'''
按钮控件:指定关联事件
'''
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
def func():
print("aaaaaaaaaaaaaaaaaaaaaaa")
# 创建按钮
button1 = tkinter.Button(win, text="按钮", command=func, width=10, height=10)
button1.pack()
button2 = tkinter.Button(win, text="按钮", command=lambda: print("bbbbbbbbbbbb"))
button2.pack()
button3 = tkinter.Button(win, text="退出", command=win.quit)
button3.pack()
win.mainloop()
4、Entry控件
'''
文本控件:用于显示单行文本
'''
import tkinter as tk
window = tk.Tk()
window.title('My Window')
window.geometry('500x300')
# 第4步,在图形界面上设定输入框控件entry并放置控件
# 添加invalidcommand属性绑定输入事件
e1 = tk.Entry(window, show='*', font=('Arial', 14)) # 显示成密文形式
e2 = tk.Entry(window, show=None, font=('Arial', 14)) # 显示成明文形式
e1.pack()
e2.pack()
# 第5步,主窗口循环显示
window.mainloop()
5、点击按钮输出输入框中的内容
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
def showinfo():
# 获取输入的内容
print(entry.get())
entry = tkinter.Entry(win)
entry.pack()
button = tkinter.Button(win, text="按钮", command=showinfo)
button.pack()
win.mainloop()
6、Text控件
'''
文本控件:用于显示多行文本
'''
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# height表示的是显示的行数
text = tkinter.Text(win, width=30, height=10)
text.pack()
str = '''盖闻天地之数,有十二万九千六百岁为一元。'''
text.insert('end', str)
win.mainloop()
7、带滚动条的Text
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
# win.geometry("400x400+200+50")
# 创建滚动条
scroll = tkinter.Scrollbar()
text = tkinter.Text(win, width=30, height=10)
# side放到窗体的哪一侧, fill填充
scroll.pack(side=tkinter.RIGHT, fill=tkinter.Y)
text.pack(side=tkinter.LEFT, fill=tkinter.Y)
# 关联
scroll.config(command=text.yview)
text.config(yscrollcommand=scroll.set)
text.pack()
str = '''盖闻天地之数,有十二万九千六百岁为一元。
将一元分为十二会,乃子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥之十二支也。
每会该一万八百岁。且就一日而论:子时得阳气,而丑则鸡鸣;
寅不通光,而卯则日出;辰时食后,而巳则挨排;
日午天中,而未则西蹉;申时晡而日落酉;
戌黄昏而人定亥。譬于大数,若到戌会之终,则天地昏蒙而万物否矣。
再去五千四百岁,交亥会之初,则当黑暗,而两间人物俱无矣,故曰混沌。
又五千四百岁,亥会将终,贞下起元,近子之会,而复逐渐开明。邵康节曰:“冬至子之半,天心无改移。
一阳初动处,万物未生时。”到此,天始有根。'''
text.insert('end', str)
win.mainloop()
8、Radiobutton圆圈单选框
import tkinter as tk
window = tk.Tk()
window.title('My Window')
window.geometry('500x300')
# 第4步,在图形界面上创建一个标签label用以显示并放置
var = tk.StringVar() # 定义一个var用来将radiobutton的值和Label的值联系在一起.
var.set('A')#默认选中A
l = tk.Label(window, bg='yellow', width=20, text='empty')
l.pack()
# 第6步,定义选项触发函数功能
def print_selection():
print(var.get())
l.config(text='you have selected ' + var.get())
# 第5步,创建三个radiobutton选项,其中variable=var, value='A'的意思就是,当我们鼠标选中了其中一个选项,把value的值A放到变量var中,然后赋值给variable
r1 = tk.Radiobutton(window, text='Option A', variable=var, value='A', command=print_selection)
r1.pack()
r2 = tk.Radiobutton(window, text='Option B', variable=var, value='B', command=print_selection)
r2.pack()
r3 = tk.Radiobutton(window, text='Option C', variable=var, value='C', command=print_selection)
r3.pack()
# 第7步,主窗口循环显示
window.mainloop()
9、Checkbutton方形多选框控件
import tkinter as tk
window = tk.Tk()
window.title('My Window')
window.geometry('500x300')
l = tk.Label(window, bg='yellow', width=20, text='empty')
l.pack()
def print_selection():
if (var1.get() == 1) & (var2.get() == 0): # 如果选中第一个选项,未选中第二个选项
l.config(text='I love only Python ')
elif (var1.get() == 0) & (var2.get() == 1): # 如果选中第二个选项,未选中第一个选项
l.config(text='I love only C++')
elif (var1.get() == 0) & (var2.get() == 0): # 如果两个选项都未选中
l.config(text='I do not love either')
else:
l.config(text='I love both') # 如果两个选项都选中
# 第5步,定义两个Checkbutton选项并放置
var1 = tk.IntVar() # 定义var1和var2整型变量用来存放选择行为返回值
var2 = tk.IntVar()
c1 = tk.Checkbutton(window, text='Python', variable=var1, onvalue=1, offvalue=0,
command=print_selection) # 传值原理类似于radiobutton部件
c1.pack()
c2 = tk.Checkbutton(window, text='C++', variable=var2, onvalue=1, offvalue=0, command=print_selection)
c2.pack()
# 第7步,主窗口循环显示
window.mainloop()
10、Listbox控件一
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
'''
列表框控件:可以包含一个或多个文本框
作用:在listbox控件的小窗口显示一个字符串
'''
# 创建一个listbox,添加几个元素
lb = tkinter.Listbox(win, selectmode=tkinter.BROWSE)
lb.pack()
for item in ["good", "nice", "handsome", "aaa", "bbb", "ccc", "ddd"]:
# 按顺序添加
lb.insert(tkinter.END, item)
# 在开始添加
lb.insert(tkinter.ACTIVE, "cool")
# 将列表当做一个元素添加
# lb.insert(tkinter.END, ["very good", "very nice"])
# 删除:参数1为开始的索引,参数2为结束的索引,如果不指定参数2,只删除第一个索引处的内容
lb.delete(1,3)
# 选中:参数1为开始的索引,参数2为结束的索引,如果不指定参数2,只选中第一个索引处的内容
lb.select_set(2,3)
# 取消选中:参数1为开始的索引,参数2为结束的索引,如果不指定参数2,只取消第一个索引处的内容
lb.select_clear(2)
# 获取到列表中的元素个数
print(lb.size())
# 获取值
print(lb.get(2,3))
# 返回当前的索引项,不是item元素
print(lb.curselection())
# 判断:一个选项是否被选中
print(lb.selection_includes(3))
win.mainloop()
11、Listbox控件二
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# 绑定变量
lbv = tkinter.StringVar()
# 与BORWSE相似,但是不支持鼠标按下后移动选中位置
lb = tkinter.Listbox(win, selectmode=tkinter.SINGLE, listvariable=lbv)
lb.pack()
for item in ["good", "nice", "handsome", "aaa", "bbb", "ccc", "ddd"]:
# 按顺序添加
lb.insert(tkinter.END, item)
# 打印当前列表中的选型
print(lbv.get())
# 设置选项
# lbv.set(("1","2","3"))
# 绑定事件
def myprint(event):
# print(lb.curselection()) # 返回下标
print(lb.get(lb.curselection())) # 返回值
lb.bind("<Double-Button-1>", myprint)
win.mainloop()
12、Scale控件
import tkinter as tk
window = tk.Tk()
window.title('My Window')
window.geometry('500x300')
# 第4步,在图形界面上创建一个标签label用以显示并放置
l = tk.Label(window, bg='green', fg='white', width=20, text='empty')
l.pack()
# 第6步,定义一个触发函数功能
def print_selection(v):
l.config(text='you have selected ' + v)
# 第5步,创建一个尺度滑条,长度200字符,从0开始10结束,以2为刻度,精度为0.01,触发调用print_selection函数
s = tk.Scale(window, label='try me', from_=0, to=10, orient=tk.HORIZONTAL, length=200, showvalue=0, tickinterval=2,
resolution=0.01, command=print_selection)
s.pack()
s.set(20)
print(s.get())
# 第7步,主窗口循环显示
window.mainloop()
13、Spinbox控件(上下箭头选择数值)
'''
数值范围控件
'''
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# 绑定变量
v = tkinter.StringVar()
def updata():
print(v.get())
# increment:步长,默认为1
# values要输入一个元组 最好不要和from和to同时使用,而且步长也没用
# command 只要值改变就会执行updata方法
sp = tkinter.Spinbox(win, from_=0, to=100, increment=5,
textvariable=v, command=updata)
# sp = tkinter.Spinbox(win, values=(0,2,4,6,8))
sp.pack()
# 赋值
v.set(20)
# 取值
print(v.get())
win.mainloop()
14、Menu顶层菜单
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# 菜单条
menubar = tkinter.Menu(win)
win.config(menu=menubar)
def func():
print("**********")
# 创建一个菜单选项
menu1 = tkinter.Menu(menubar, tearoff=False)
# 给菜单选项添加内容
for item in ['python','c','java','c++', 'c#','php','B','退出']:
if item == '退出':
# 添加分割线
menu1.add_separator()
menu1.add_command(label=item, command=win.quit)
else:
menu1.add_command(label=item, command=func)
# 向菜单条上添加菜单选项
menubar.add_cascade(label='语言', menu=menu1)
win.mainloop()
15、Menu鼠标右键菜单
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# 菜单条
menubar = tkinter.Menu(win)
def func():
print("**********")
# 菜单
menu = tkinter.Menu(menubar, tearoff=False)
# 给菜单选项添加内容
for item in ['python','c','java','c++', 'c#','php','B','退出']:
if item == '退出':
# 添加分割线
menu.add_separator()
menu.add_command(label=item, command=win.quit)
else:
menu.add_command(label=item, command=func)
menubar.add_cascade(label="语言", menu=menu)
def showMenu(event):
menubar.post(event.x_root, event.y_root)
win.bind("<Button-3>", showMenu)
win.mainloop()
16、Combobox下拉选项控件
import tkinter
from tkinter import ttk
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# 绑定变量
cv = tkinter.StringVar()
com = ttk.Combobox(win, textvariable=cv,state="readonly")# 不设置会导致可以直接修改
com.pack()
# 设置下拉数据
com["value"] = ("黑龙江", "吉林", "辽宁")
# 设置默认值
com.current(0)
# 绑定事件
def func(event):
print(com.get())
print(cv.get())
com.bind("<<ComboboxSelected>>", func)
win.mainloop()
17、messagebox弹出窗口
import tkinter as tk # 使用Tkinter前需要先导入
import tkinter.messagebox # 要使用messagebox先要导入模块
window = tk.Tk()
window.title('My Window')
window.geometry('500x300')
# 第5步,定义触发函数功能
def hit_me():
tkinter.messagebox.showinfo(title='Hi', message='你好!') # 提示信息对话窗
tkinter.messagebox.showwarning(title='Hi', message='有警告!') # 提出警告对话窗
tkinter.messagebox.showerror(title='Hi', message='出错了!') # 提出错误对话窗
print(tkinter.messagebox.askquestion(title='Hi', message='你好!')) # 询问选择对话窗return 'yes', 'no'
print(tkinter.messagebox.askyesno(title='Hi', message='你好!')) # return 'True', 'False'
print(tkinter.messagebox.askokcancel(title='Hi', message='你好!')) # return 'True', 'False'
# 第4步,在图形界面上创建一个标签用以显示内容并放置
tk.Button(window, text='hit me', bg='green', font=('Arial', 14), command=hit_me).pack()
# 第6步,主窗口循环显示
window.mainloop()
18、弹出窗口接收数据
import tkinter as tk
from tkinter.simpledialog import askstring, askinteger, askfloat
# 接收一个整数
def print_integer():
res = askinteger("Spam", "Egg count", initialvalue=12*12)
print(res)
# 接收一个浮点数
def print_float():
res = askfloat("Spam", "Egg weight\n(in tons)", minvalue=1, maxvalue=100)
print(res)
# 接收一个字符串
def print_string():
res = askstring("Spam", "Egg label")
print(res)
root = tk.Tk()
tk.Button(root, text='取一个字符串', command=print_string).pack()
tk.Button(root, text='取一个整数', command=print_integer).pack()
tk.Button(root, text='取一个浮点数', command=print_float).pack()
root.mainloop()
19、Notebook选项卡标签(很好玩)
import tkinter as tk #装载tkinter模块,用于Python3
from tkinter import ttk #装载tkinter.ttk模块,用于Python3
root =tk.Tk() # 创建窗口对象
root.title(string = 'ttk.Notebook演示') #设置窗口标题
root.geometry('400x300+200+200')
tabControl = ttk.Notebook(root) #创建Notebook
tab1 = tk.Frame(tabControl,bg='blue') #增加新选项卡
tabControl.add(tab1, text='信息窗') #把新选项卡增加到Notebook
tab2 = tk.Frame(tabControl,bg='yellow')
tabControl.add(tab2, text='综合信息')
tab3 = tk.Frame(tabControl,bg='green')
tabControl.add(tab3, text='技术分析')
tab4 = tk.Frame(tabControl,bg='blue')
tabControl.add(tab4, text='编写代码')
tab5 = tk.Frame(tabControl,bg='blue')
tabControl.add(tab5, text='模拟回测')
tabControl2 = ttk.Notebook(root)
tab6 = ttk.Frame(tabControl2)
tabControl2.add(tab6, text='双色球')
tabControl.add(tabControl2, text='双色球')
tabControl.pack(expand=1, fill="both")
tabControl.select(tab1) #选择tab1
root.mainloop() # 进入消息循环
20、分割控件
# 分隔控件的作用就是把控件分隔为几个部分。分隔控件有2两种:水平(HORIZONTAL )或者垂直(VERTICAL )。
# 如果是使用grid布局管理器,需要使用sticky来拉伸分隔控件,否则可能只是窄窄的一条线。
# 如果是使用pack布局管理器,使用使用fill来拉伸控件。
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.geometry('320x240')
#设置风格
# s=ttk.Style()
# s.configure('red.TSeparator',background='red')
# b=ttk.Separator(root,orient='horizontal',
# style='red.TSeparator')
b=ttk.Separator(root,orient='horizontal')
a=ttk.Button(root,text='Button')
a.pack()
b.pack(fill=tk.X)
root.mainloop()
from tkinter import *
from tkinter import ttk
root = Tk()
root.geometry("400x400+30+150")
ttk.Label(root, text="line1").grid(row=1, column=1)
ttk.Label(root, text="line2").grid(row=1, column=3)
ttk.Label(root, text="line3").grid(row=3, column=1)
ttk.Label(root, text="line4").grid(row=3, column=3)
sh = ttk.Separator(root, orient=HORIZONTAL)
sh.grid(row=2, column=1, columnspan=3, sticky="we")
sv = ttk.Separator(root, orient=VERTICAL)
sv.grid(row=1, column=2, rowspan=3, sticky="ns")
root.columnconfigure(1, weight=1)
root.rowconfigure(1, weight=1)
root.columnconfigure(3, weight=1)
root.rowconfigure(3, weight=1)
#问题是您没有被grid_columnconfigure要求告诉tkinter如何处理额外的空间。
# 由于您没有告诉内部框架如何处理多余的空间,因此将其留空。
# 当小部件放置在其父级中并展开时,您的内部小部件未使用多余的空间。
root.mainloop()
21、Frame控件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
'''
框架控件:在桌面上显示一个矩形区域,多作为一个容器控件
'''
frm = tkinter.Frame(win)
frm.pack()
# left
frm_l = tkinter.Frame(frm)
tkinter.Label(frm_l, text="左上", bg="pink").pack(side=tkinter.TOP)
tkinter.Label(frm_l, text="左下", bg="blue").pack(side=tkinter.TOP)
frm_l.pack(side=tkinter.LEFT)
# right
frm_r = tkinter.Frame(frm)
tkinter.Label(frm_r, text="右上", bg="green").pack(side=tkinter.TOP)
tkinter.Label(frm_r, text="右下", bg="red").pack(side=tkinter.TOP)
frm_r.pack(side=tkinter.RIGHT)
win.mainloop()
21、表格数据(Treeview)
https://blog.csdn.net/weixin_42268054/article/details/82902296
from tkinter import ttk
from tkinter import *
root = Tk() # 初始框的声明
columns = ("姓名", "IP地址")
treeview = ttk.Treeview(root, height=18, show="headings", columns=columns) # 表格
treeview.column("姓名", width=100, anchor='center') # 表示列,不显示
treeview.column("IP地址", width=300, anchor='center')
treeview.heading("姓名", text="姓名") # 显示表头
treeview.heading("IP地址", text="IP地址")
treeview.pack(side=LEFT, fill=BOTH)
name = ['电脑1', '服务器', '笔记本']
ipcode = ['10.13.71.223', '10.25.61.186', '10.25.11.163']
for i in range(min(len(name), len(ipcode))): # 写入数据
treeview.insert('', i, values=(name[i], ipcode[i]))
def treeview_sort_column(tv, col, reverse): # Treeview、列名、排列方式
l = [(tv.set(k, col), k) for k in tv.get_children('')]
l.sort(reverse=reverse) # 排序方式
# rearrange items in sorted positions
for index, (val, k) in enumerate(l): # 根据排序后索引移动
tv.move(k, '', index)
tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse)) # 重写标题,使之成为再点倒序的标题
def set_cell_value(event): # 双击进入编辑状态
for item in treeview.selection():
# item = I001
item_text = treeview.item(item, "values")
# print(item_text[0:2]) # 输出所选行的值
column = treeview.identify_column(event.x) # 列
row = treeview.identify_row(event.y) # 行
cn = int(str(column).replace('#', ''))
rn = int(str(row).replace('I', ''))
entryedit = Text(root, width=10 + (cn - 1) * 16, height=1)
entryedit.place(x=16 + (cn - 1) * 130, y=6 + rn * 20)
def saveedit():
treeview.set(item, column=column, value=entryedit.get(0.0, "end"))
entryedit.destroy()
okb.destroy()
okb = ttk.Button(root, text='OK', width=4, command=saveedit)
okb.place(x=90 + (cn - 1) * 242, y=2 + rn * 20)
def newrow():
name.append('待命名')
ipcode.append('IP')
treeview.insert('', len(name) - 1, values=(name[len(name) - 1], ipcode[len(name) - 1]))
treeview.update()
newb.place(x=120, y=(len(name) - 1) * 20 + 45)
newb.update()
treeview.bind('<Double-1>', set_cell_value) # 双击左键进入编辑
newb = ttk.Button(root, text='新建联系人', width=20, command=newrow)
newb.place(x=120, y=(len(name) - 1) * 20 + 45)
for col in columns: # 绑定函数,使表头可排序
treeview.heading(col, text=col, command=lambda _col=col: treeview_sort_column(treeview, _col, False))
'''
1.遍历表格
t = treeview.get_children()
for i in t:
print(treeview.item(i,'values'))
2.绑定单击离开事件
def treeviewClick(event): # 单击
for item in tree.selection():
item_text = tree.item(item, "values")
print(item_text[0:2]) # 输出所选行的第一列的值
tree.bind('<ButtonRelease-1>', treeviewClick)
3、删除treeview
def delButton(tree):
x=tree.get_children()
for item in x:
tree.delete(item)
------------------------------
鼠标左键单击按下1/Button-1/ButtonPress-1
鼠标左键单击松开ButtonRelease-1
鼠标右键单击3
鼠标左键双击Double-1/Double-Button-1
鼠标右键双击Double-3
鼠标滚轮单击2
鼠标滚轮双击Double-2
鼠标移动B1-Motion
鼠标移动到区域Enter
鼠标离开区域Leave
获得键盘焦点FocusIn
失去键盘焦点FocusOut
键盘事件Key
回车键Return
控件尺寸变Configure
------------------------------
'''
root.mainloop() # 进入消息循环
22、树状数据
import tkinter
from tkinter import ttk
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
tree = ttk.Treeview(win)
tree.pack()
# 添加一级树枝
treeF1 = tree.insert("",0,"中国",text= "中国Chi", values=("F1"))
treeF2 = tree.insert("",1,"美国",text= "美国USA", values=("F1"))
treeF3 = tree.insert("",2,"英国",text= "英国UK", values=("F1"))
# 二级树枝
treeF1_1 = tree.insert(treeF1,0,"黑龙江",text="中国黑龙江",values=("F1_1"))
treeF1_2 = tree.insert(treeF1,1,"吉林",text="中国吉林",values=("F1_2"))
treeF1_3 = tree.insert(treeF1,2,"辽宁",text="中国辽宁",values=("F1_3"))
treeF2_1 = tree.insert(treeF2,0,"aaa",text="aaaa",values=("F2_1"))
treeF2_2 = tree.insert(treeF2,1,"bbb",text="bbbb",values=("F2_2"))
treeF2_3 = tree.insert(treeF2,2,"ccc",text="cccc",values=("F2_3"))
# 三级树枝
treeF1_1_1 = tree.insert(treeF1_1,0,"哈尔滨",text="黑龙江哈尔滨")
treeF1_1_2 = tree.insert(treeF1_1,1,"五常",text="黑龙江五常")
win.mainloop()
23、组件的鼠标点击事件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
def func(event):
print(event.x, event.y)
# <Button-1> 鼠标左键
# <Button-2> 鼠标滚轮
# <Button-1> 鼠标右键
# <Double-Button-1> 鼠标双击左键
# <Triple-Button-1> 鼠标三击左键
button1 = tkinter.Button(win, text="leftmouse button")
# bind 给控件绑定数据(参数一是绑定的事件,参数二是触发事件的函数)
button1.bind("<Button-1>", func)
button1.pack()
win.mainloop()
24、组件的鼠标移动事件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# <B1-Motion> 左键移动
# <B2-Motion> 中键移动
# <B3-Motion> 右键移动
label = tkinter.Label(win, text="*********")
label.pack()
def func(event):
print(event.x, event.y)
label.bind("<B1-Motion>", func)
win.mainloop()
25、组件的鼠标释放事件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# <ButtonRelease-1> 释放鼠标左键
# <ButtonRelease-2> 释放鼠标中键
# <ButtonRelease-3> 释放鼠标右键
label = tkinter.Label(win, text="*********", bg="red")
label.pack()
def func(event):
print(event.x, event.y)
label.bind("<ButtonRelease-1>", func)
win.mainloop()
26、进入和离开事件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# <Enter> 当鼠标进入控件时触发事件
# <Leave> 当鼠标离开控件时触发事件
label = tkinter.Label(win, text="*********", bg="red")
label.pack()
def func(event):
print(event.x, event.y)
label.bind("<Enter>", func)
label.bind("<Leave>", func)
win.mainloop()
27、响应所有按键的事件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# <Key> 响应所有的按键(要有焦点)
label = tkinter.Label(win, text="*********", bg="red")
# 设置焦点
label.focus_set()
label.pack()
def func(event):
print("event.char=", event.char)
print("event.keycode=", event.keycode)
label.bind("<Key>", func)
win.mainloop()
28、响应特殊按键事件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# <Shift_L> 只响应左侧的shift键
# <Shift_R>
# <F5>
# <Return> 也就是回车键
# <BackSpace> 返回,也就是退格键
label = tkinter.Label(win, text="*********", bg="red")
# 设置焦点
label.focus_set()
label.pack()
def func(event):
print("event.char=", event.char)
print("event.keycode=", event.keycode)
label.bind("<Shift_L>", func)
win.mainloop()
29、指定按键事件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
label = tkinter.Label(win, text="*********", bg="red")
# 设置焦点
label.focus_set()
label.pack()
def func(event):
print("event.char=", event.char)
print("event.keycode=", event.keycode)
win.bind("a", func) # 注意前面改成了win,只需要写出按键名即可
win.mainloop()
30、组合按键事件
import tkinter
win = tkinter.Tk()
win.title("yudanqu")
win.geometry("400x400+200+50")
# <Control-Alt-a>
# <Shift-Up>
# 只是control+alt不行
label = tkinter.Label(win, text="*********", bg="red")
# 设置焦点
label.focus_set()
label.pack()
def func(event):
print("event.char=", event.char)
print("event.keycode=", event.keycode)
win.bind("<Control-Alt-a>", func) # 注意前面改成了win,只需要写出按键名即可
win.mainloop()
综合案例
多功能计算器
import tkinter,time,decimal,math,string #加载各种库
window=tkinter.Tk() #创建tkinter对象
window.title('计算器') #设置标题
window.resizable(0,0) #设置大小不可变
#全局变量,storage存储列表,vartext存储字符串,result存储结果,symbol存储符号
global storage, vartext, result, symbol
result = symbol = None #变量result和symbol设置值为None
vartext = tkinter.StringVar() #创建StringVar对象
storage = [] #变量storage设置为列表
#按键值类
class key_press:
global storage, vartext, result, symbol #引用全局变量
#构造方法,设置按键属性
def __init__(self,anjian):
self.key = anjian #按键名称
#添加,用于将按键值添加到storage列表,再将storage的值设置为vartext的值
def jia(self):
storage.append(self.key) #将按键值添加到storage列表
vartext.set(''.join(storage)) #将storage的值连接生成一个新的字符串,并设置为vartext的值
#删除功能
def retreat(self):
storage.pop() #移除storage列表的值(默认最后一个元素)
vartext.set(''.join(storage)) #将storage的值连接生成一个新的字符串,并设置为vartext的值
#清除功能
def clear(self):
storage.clear() #清空storage列表
vartext.set('') #设置vartext的值为空
result = None #变量result结果改为None
symbol = None #变量symbol结果改为None
#切换正负功能
def plus_minus(self):
if storage[0]: #先判断storage[0]是否有值
if storage[0] == '-': #如果storage[0]值为“-”
storage[0] = '+' #将storage[0]值改为“+”
elif storage[0] == '+': #如果storage[0]值为“+”
storage[0] = '-' #将storage[0]值为“-”
else:
storage.insert(0, '-') #如果storage[0]的值既不是“+”,又不是“-”,则表示没有符号,添加一个“-”
vartext.set(''.join(storage)) #将storage的值连接生成一个新的字符串,并设置为vartext的值
#添加小数点功能
def decimal_point(self):
if storage.count('.') >= 1: #如果已经存在小数点,则什么都不做
pass
else:
if storage == []: #如果storage为空
storage.append('0') #给storage队列添加0
storage.append('.') #给storage队列添加.
vartext.set(''.join(storage)) #将storage的值连接生成一个新的字符串,并设置为vartext的值
#运算
def operation(self):
global storage, vartext, result, symbol #引用全局变量
if vartext.get() == '': #如果vartext中没有值,则什么也不做
pass
else:
get1 = decimal.Decimal(vartext.get()) #获取输入的数值
if self.key in ('1/x','sqrt'): #如果按键值属于'1/x'和'sqrt'其中之一
if self.key == '1/x': #如果按键值是“1/x”
result = 1/get1 #将1/变量get1的结果赋值给变量result
elif self.key == 'sqrt': #如果按键值是“sqrt”
result = math.sqrt(get1) #计算变量get1的平方根
elif self.key in ('+','-','*','/','='): #判断按键值
if symbol is not None: #如果symbol变量不是None
get1 = decimal.Decimal(result) #获取第一次输入的数值
get2 = decimal.Decimal(vartext.get()) #获取第二次输入的数值
if symbol == '+': #如果符号是“+”
result = get1 + get2 #相加
elif symbol == '-': #如果符号是“-”
result = get1 - get2 #相减
elif symbol == '*': #如果符号是“*”
result = get1 * get2 #相乘t
elif symbol == '/': #如果符号是“/”
result = get1 / get2 #相除
else: #如果没有输入符号
result = get1 #获取get1的值
if self.key == '=': #如果输入的键值为“=”
symbol = None #变量symbol则赋值为None
else: #输入的键值不为“=”
symbol = self.key #将输入的键值赋值给symbol
print(symbol) #输出变量symbol,表示符号
print(result) #输出变量result,表示结果
vartext.set(str(result)) #将结果转为字符串形式,并设置为vartext的值
storage.clear() #清空storage列表
#计算器布局
def layout(window):
global storage, vartext, result, symbol #引用全局变量
#设置顶部标签,用于展示按键的值
entry1 = tkinter.Label(window, width=30, height=2, bg='white', anchor='se',\
textvariable=vartext)
entry1.grid(row=0, columnspan=5)
#添加按钮
buttonJ=tkinter.Button(window,text='←',width=5,command=key_press('c').retreat)
buttonCE=tkinter.Button(window,text='保存',width=5)
buttonC=tkinter.Button(window,text=' C ',width=5,command=key_press('c').clear)
button12=tkinter.Button(window,text='±',width=5,\
command=key_press('c').plus_minus)
buttonD=tkinter.Button(window,text='√',width=5,\
command=key_press('sqrt').operation)
buttonJ.grid(row=2,column=0)
buttonCE.grid(row=2,column=1)
buttonC.grid(row=2,column=2)
button12.grid(row=2,column=3)
buttonD.grid(row=2,column=4)
button7=tkinter.Button(window,text=' 7 ',width=5,command=key_press('7').jia)
button8=tkinter.Button(window,text=' 8 ',width=5,command=key_press('8').jia)
button9=tkinter.Button(window,text=' 9 ',width=5,command=key_press('9').jia)
buttonc=tkinter.Button(window, text=' / ',width=5,command=key_press('/').operation)
buttonf= tkinter.Button(window, text='删除',width=5)
button7.grid(row=3,column=0)
button8.grid(row=3,column=1)
button9.grid(row=3,column=2)
buttonc.grid(row=3,column=3)
buttonf.grid(row=3,column=4)
button4=tkinter.Button(window,text=' 4 ',width=5,command=key_press('4').jia)
button5=tkinter.Button(window,text=' 5 ',width=5,command=key_press('5').jia)
button6=tkinter.Button(window,text=' 6 ',width=5,command=key_press('6').jia)
buttonx=tkinter.Button(window,text=' * ',width=5,command=key_press('*').operation)
buttonfs=tkinter.Button(window,text='1/x',width=5,\
command=key_press('1/x').operation)
button4.grid(row=4,column=0)
button5.grid(row=4,column=1)
button6.grid(row=4,column=2)
buttonx.grid(row=4,column=3)
buttonfs.grid(row=4,column=4)
button1 = tkinter.Button(window, text=' 1 ',width=5,command=key_press('1').jia)
button2 = tkinter.Button(window, text=' 2 ',width=5,command=key_press('2').jia)
button3 = tkinter.Button(window, text=' 3 ',width=5,command=key_press('3').jia)
button_= tkinter.Button(window, text=' - ',width=5,command=key_press('-').operation)
buttondy= tkinter.Button(window, text=' \n = \n ',width=5,\
command=key_press('=').operation)
button1.grid(row=5, column=0)
button2.grid(row=5, column=1)
button3.grid(row=5, column=2)
button_.grid(row=5, column=3)
buttondy.grid(row=5, column=4,rowspan=2)
button0=tkinter.Button(window,text=' 0 ',width=11,command=key_press('0').jia)
buttonjh = tkinter.Button(window,text=' . ',width=5,\
command=key_press('c').decimal_point)
buttonjia=tkinter.Button(window,text=' + ',width=5,\
command=key_press('+').operation)
button0.grid(row=6,column=0,columnspan=2)
buttonjh.grid(row=6,column=2)
buttonjia.grid(row=6,column=3)
layout(window) #window窗口应用layout布局
window.mainloop()
treeview、爬虫、下拉选择综合案例
from tkinter import *
import tkinter.messagebox
from tkinter import ttk
import requests
import re
def show_data():
global data_dict
the_tpye=value1.get()
the_year=2019-eval(value2.get()[:-1])
for i in data_dict:
if i ==the_tpye:
tkinter.messagebox.showinfo(title='Hi', message='%s年%s的数据为%s亿元'%(value2.get(),value1.get()[:-4],data_dict[i][the_year]))
def spyder():
global data_dict
url = 'http://data.stats.gov.cn/easyquery.htm?m=QueryData&dbcode=hgnd&rowcode=zb&colcode=sj&wds=%5B%5D&dfwds=%5B%7B%22wdcode%22%3A%22zb%22%2C%22valuecode%22%3A%22A0201%22%7D%5D&k1=1592276489221&h=1'
response = requests.get(url).content.decode()
data_list = re.findall('"strdata":"(.*?)"}?', response)
data_dict = {'国民总收入(亿元)': data_list[0:10], '国内生产总值(亿元)': data_list[10:20], '第一产业增加值(亿元)': data_list[20:30],
'第二产业增加值(亿元)': data_list[30:40], '第三产业增加值(亿元)': data_list[40:50], '人均国内生产总值(元)': data_list[50:60]}
for i in data_dict:
tv.insert('', 'end', values=[i]+data_dict[i])
data_dict={}
win = Tk()
win.title("国内生产总值查询工具")
win.geometry('730x400')
lb1 = Label(win, text="指标类型", font=('tahoma 12 normal', 10))
lb1.grid(column=0, row=2)
lb2 = Label(win, text="查询年份", font=('tahoma 12 normal', 10))
lb2.grid(column=0, row=4)
b1 = Button(win, text='点击爬取信息',font=('tahoma 12 normal', 10),height=2, command=spyder)
b1.grid(column=0, row=1)
b2 = Button(win, text='点击查询',font=('tahoma 12 normal', 10),height=2, command=show_data)
b2.grid(column=0, row=6)
# Define tkinter data type
value1 = StringVar()
cbx_1 = ttk.Combobox(win, width=16, height=8, textvariable=value1)
cbx_1.grid(column=0, row=3)
cbx_1["values"] = ['国民总收入(亿元)','国内生产总值(亿元)','第一产业增加值(亿元)','第二产业增加值(亿元)','第三产业增加值(亿元)','人均国内生产总值(元)']
cbx_1.current(0)
value2 = StringVar()
cbx_2 = ttk.Combobox(win, width=16, height=8,textvariable=value2)
cbx_2.grid(column=0, row=5)
cbx_2["values"] = ["2019年","2018年","2017年","2016年","2015年","2014年","2013年","2012年","2011年","2010年"]
cbx_2.current(0)
area = ('指标', "2019年","2018年","2017年","2016年","2015年","2014年","2013年","2012年","2011年","2010年")
ac=('指标', "2019年","2018年","2017年","2016年","2015年","2014年","2013年","2012年","2011年","2010年")
dc=('指标', "2019年","2018年","2017年","2016年","2015年","2014年","2013年","2012年","2011年","2010年")
tv = ttk.Treeview(win, columns=ac, show='headings',height=7, displaycolumns=dc)
tv.column(ac[0], width=130, anchor='c')
tv.heading(ac[0], text='指标')
for i in range(1,11):
tv.column(ac[i], width=60, anchor='c')
tv.heading(ac[i], text=area[i])
tv.grid(column=0, row=7)
win.mainloop()