Python:GUI库tkinter(二)
学习自:
Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) - 洪卫 - 博客园
1、控件
这一部分已经在前一篇博文说过了,此处额外补充说明一些控件
控件 | 说明 |
Canvas | 画布。这个部件可以用来绘制图表和图,创建图形编辑器,实现定制窗口部件 |
CheckButton | 单选框。代表一个变量,它有两个不同的值,根据按钮是否点击会在这两个值之间切换。 |
Combobox | 下拉组合框 |
Entrt | 输入框 |
Spinbox | 可选输入控件 |
Frame | 框架。框架有边框和背景,当创建一个应用程序或者dialog时,框架被用来组织其它的窗口部件。 |
Label | 显示一个文本或图片 |
Menu | 菜单条。 |
Menubutton | 菜单按钮 |
Message | 一个可调整文本,能够自动调整文本到给定的宽度或者比率。 |
Radiobutton | 多个选项,选择其中之一。被选中的选项将作为这个控件代表变量的值,并且清除与这一变量相关的其他Radiobutton |
Scale | 允许通过一个滑块设置一个数字 |
Scrollbar | 配合Canvas、Entry、Listbox、Text部件使用的滚动条 |
Text | 格式化文本显示。允许用不同的格式和属性来显示和编辑文本,同时支持内嵌图像和窗口。 |
ScrolledText | 滚动条文本框,(超出范围时可以上下拖动滚动条) |
Toplevel | 一个单独的、最上边的窗口显示。 |
Progressbar | 进度条 |
filedialog | 文件对话框 |
messageBox | 消息框 |
Tkinter中窗口部件类没有分级,所有的窗口部件类在树中都是兄弟关系。
所有这些窗口部件提供了Misc和几何管理方法、配置管理方法和部件自己定义的另外的方法。此外,Toplevel类也提供了窗口管理接口,这意味着一个典型的窗口部件提供了大约150种方法。
2、实践
①主窗口与Label
from tkinter import *
# 1、实例化Object,建立窗口window
window = Tk()
# 2、给窗口起名字,用title方法
window.title('My Window')
# 3、设置窗口的大小,用geometry方法
window.geometry('500x300') # 这里是字母x
#4、在界面上设置Label
L = Label(
window, text='你好!This is Tkinter', bg='green',
font=('Arial', 12), width=30, height=10
)
#说明:bg为背景,font为字体,width与height的单位为字符
#5、部署Label
L.pack() #未设置参数时,自动调节尺寸
#部署Label的方法有pack()和place()两种
#6、主窗口window循环显示
window.mainloop()
测试效果:
②Button
Button是一个标准Tkinter窗口部件,用于实现各种按钮。按钮可以包含文本或者图像。如果将按钮与某个函数(通过command参数)相关联。当这个按钮被按下时,Tkinter自动调用相关联的函数或者方法。
按钮仅能显示一种字体,但是这个文本可以跨行。另外,文本中的字母可以有下划线,例如标明该按钮功能对应的快捷键。默认情况下,Tab键用于将焦点移动到一个按钮部件。
按钮通常在工具条中或应用程序窗口中,并且用来接收或者忽略输入在对话框中的数据。关于按钮和输入数据的配合,可以参看Checkbutton和Radiobutton部件。
创建Button
按钮创建时,需要指定按钮的内容(文本、位图、图像)和一个当前按钮被按下时的回调函数:
b = tkinter.Button(window , text='hit me',command=hit_me)
可以创建一个什么都不做的按钮,只需要把回调函数command = DISABLED
例子
from tkinter import *
# 1、实例化Object,建立窗口window
window = Tk()
# 2、窗口名
window.title('My Window')
# 3、设置窗口大小
window.geometry('500x300')
# 4、在图形界面上设置标签
# 将Label标签的内容设置为字符类型,用var来接受hit_me函数传出内容
# 用以显示在标签上
var = StringVar()
L = Label(
window, textvariable=var,
bg='green', fg='white',
font=('arial', 12),
width=30, height=2
) # 这里的长和高是字符的长和高
L.pack()
# 定义一个功能函数
on_hit = False
def hit_me():
global on_hit
if on_hit == False:
on_hit = True
var.set('You hit me')
else:
on_hit = False
var.set('')
# 5、设置Button按钮
b = Button(
window, text='hit me', font=('Arial', 12),
width=10, height=1, command=hit_me
)
b.pack()
# 6、主窗口循环展示
window.mainloop()
③Entry:单行文本输入框
例子
from tkinter import *
window = Tk()
window.title('My Window')
window.geometry('300x500')
e1=Entry(window,show='*',font=('Arial',14))#显示成密文形式
e2=Entry(window,font=('Arial',14))#显示成明文形式
e1.pack()
e2.pack()
window.mainloop()
④Text:多行文本
https://www.jianshu.com/p/bf3b49c66801?from=singlemessage
Text是一个多行文本区域,显示多行文本,可以用来收集用户输入的文字,格式化文本显示。
例子
from tkinter import *
window = Tk()
window.title('My Window')
window.geometry('500x300')
e = Entry(window)
e.pack()
# 定义按钮的事件函数insert_point与insert_end
def insert_point(): # 在鼠标焦点处插入输入内容
var = e.get()
t.insert('insert', var)
def insert_end():
var = e.get()
t.insert('end', var)
B1 = Button(
window, text='Insert_Point', width=10,
height=2, command=insert_point
)
B1.pack()
B2=Button(
window,text='Insert_End',width=10,
height=2,command=insert_end
)
B2.pack()
t = Text(window,height=3)
t.pack()
window.mainloop()
⑤Listbox:列表框
相关参数、方法:https://blog.csdn.net/qq_41556318/article/details/85108351
https://blog.csdn.net/aa1049372051/article/details/51878578
主要方法:
curselection:返回选中选项的序号
delete:删除一些项
insert:插入一些项
size:选中的数量
提供一个由很多选项组成的列表,可以从中选择需要的项
from tkinter import *
window=Tk()
window.title('My Window')
window.geometry('500x300')
#创建一个Label
var1=StringVar()
L=Label(window,bg='green',fg='yellow',font=('Arial',12),
width=10,textvariable=var1)
L.pack()
def print_selection():
value = lb.get(lb.curselection())
var1.set(value)
b1=Button(window,text='Print Selection',width=15,
height=2,command=print_selection)
b1.pack()
var2=StringVar()
var2.set((1,2,3,4))
lb=Listbox(window,listvariable=var2)
list_items=[11,22,33,44]
for item in list_items:
lb.insert('end',item) #从最后一个位置开始插入
lb.insert(1,'first')
lb.insert(2,'second')
lb.delete(2)
lb.pack()
window.mainloop()
为ListBox绑定事件,使得我们在选中其中某一项时触发该事件:
def func(): pass lb=ListBox(...).place(...) lb.bind('<Double-Button-1>',func)
这段代码的意思是,当双击其中某一项时,调用函数func
由于ListBox没有command参数,所以不能用command与方法绑定,而是直接用bind和事件以及事件响应函数绑定,这样当相应事件触发时就能调用该响应函数。
⑥Radiobutton:多值单选
from tkinter import *
window=Tk()
window.title('My Window')
window.geometry('500x300')
var=StringVar()
l=Label(window,bg='yellow',width=20,text='empty')
l.pack()
def print_selection():
l.config(text='you have selected'+var.get())
#创建三个radiobutton选项
#其中variable=var,value='A'说明:
# 选择了该项,那么变量var则赋值为'A'
r1=Radiobutton(window,text='option A',variable=var,value='A',
command=print_selection)
r1.pack()
r2=Radiobutton(window,text='option B',variable=var,value='B',
command=print_selection)
r2.pack()
r3=Radiobutton(window,text='option C',variable=var,value='C',
command=print_selection)
r3.pack()
window.mainloop()
⑦Checkbutton:多选按钮
from tkinter import *
window=Tk()
window.title('My Window')
window.geometry('500x300')
l=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')
var1=IntVar()
var2=IntVar()
c1=Checkbutton(window,text='Python',variable=var1,onvalue=1,offvalue=0,command=print_selection)
c2=Checkbutton(window,text='C++',variable=var2,onvalue=1,offvalue=0,command=print_selection)
c1.pack()
c2.pack()
window.mainloop()
⑧Scale:刻度滑块、动态取值
from tkinter import *
window = Tk()
window.title('My Window')
window.geometry('500x300')
l = Label(window, bg='green', fg='white', width=20, text='empty')
l.pack()
def print_selection(v):
l.config(text='You have selected ' + v)
s = Scale(window, from_=0, to=10, orient=HORIZONTAL,
length=200, showval=0, tickinterval=2,
resolution=0.01, command=print_selection)
s.pack()
window.mainloop()
⑨Canvas:画布
提供绘图功能(直线、椭圆、多边形、矩形),可以包含图形或者位图,用来绘制图标和图,创建图形编辑器,实现定制窗口部件
什么时候用:比如用户交互界面等,需要提供设计的图标、图形、logo等信息可以用到画布Canvas
from tkinter import *
window = Tk()
window.title('My Window')
window.geometry('500x300')
canvas=Canvas(window,bg='green',width=500,height=200)
image_file=PhotoImage(file='Squirrel.png')
image=canvas.create_image(250,0,anchor='n',image=image_file)
#定义多边形参数,然后在画布上画出指定图形
x0,y0,x1,y1=100,100,150,150
line=canvas.create_line(x0-50,y0-50,x1-50,y1-50)
oval=canvas.create_oval(x0+120,y0+50,x1+120,y1+50,fill='yellow')
arc=canvas.create_arc(x0,y0+50,x1,y1+50,start=0,extent=180)
rect=canvas.create_rectangle(330,30,330+20,30+20)
canvas.pack()
def moveit():
canvas.move(rect,2,2) #移动正方形rect
b=Button(window,text='move item',command=moveit).pack()
window.mainloop()
使用canvas.move(xxx,x,y),可以移动画布上的对象xxx
⑩Menu:工具栏菜单条
from tkinter import *
window = Tk()
window.title('My Window')
window.geometry('500x300')
l=Label(window,text=' ',bg='green')
l.pack()
counter=0
def do_job():
global counter
l.config(text='do '+str(counter))
counter+=1
#创建一个菜单栏,我们可以把它理解为一个容器,在窗口的上方
menubar=Menu(window)
#创建一个File菜单项(默认不下拉,下拉内容包括New,Open,Save,Exit功能项)
filemenu=Menu(menubar,tearoff=1)
#将上面定义的控菜单命名为File,放入菜单栏中,即装入那个容器中
menubar.add_cascade(label='File',menu=filemenu)
#在File中加入New、Open、Save等小彩蛋,即我们平常看到的
#下拉菜单,每一个小菜单对应命令操作
filemenu.add_command(label='New',command=do_job)
filemenu.add_command(label='Open',command=do_job)
filemenu.add_command(label='Save',command=do_job)
filemenu.add_separator()#添加一条分割线
#tkinter库中的quit函数用于退出
filemenu.add_command(label='Exit',command=window.quit)
#创建一个Edit菜单项,默认下拉,下拉内容包括Cut、Copy、Paste
editmenu=Menu(menubar,tearoff=1)
#将上面定义的控菜单命名为Edit,放在菜单栏中
menubar.add_cascade(label='Edit',menu=editmenu)
#同样在Edit中加入Cut、Copy、Paste等小命令功能单元,如果
#点击这些单元,就会触发do_fob的功能
editmenu.add_command(label='Cut',command=do_job)
editmenu.add_command(label='Copy',command=do_job)
editmenu.add_command(label='Paste',command=do_job)
#创建二级菜单,即菜单项中的菜单
submenu=Menu(filemenu)
filemenu.add_cascade(label='Import',menu=submenu,underline=0)
#创建三级菜单
submenu.add_command(label='SubMenu_1',command=do_job)
window.config(menu=menubar)
window.mainloop()
⑪Frame:窗口
用来承载其它GUI元素,是一个在Windows上分离小区域的部件,它能将Windows分成不同的区,然后存放不同的其他部件,同一个Frame上也能够再分成两个Frame
使用时机:
在像软件或者网页交互界面等,有不同的界面逻辑层级和功能区域划分时可以用到,让交互界面逻辑更加清晰。
from tkinter import *
window=Tk()
window.title('My Window')
window.geometry('300x500')
#创建一个Label用以显示内容并且放置
Label(window,text='on the window',bg='red',font=('Arial',16)).pack()
#创建一个主Frame
frame=Frame(window)
frame.pack()
#创建次级Frame,放置在主Frame之上
framel=Frame(frame)#左frame
framer=Frame(frame)
framel.pack(side='left')
framer.pack(side='right')
#创建三组Label,为次级Frame中的内容,分为左右区域
#用不同颜色标识
Label(framel,text='on the framel1',bg='green').pack()
Label(framel,text='on the framel2',bg='green').pack()
Label(framel,text='on the framel3',bg='green').pack()
Label(framer,text='on the framer1',bg='yellow').pack()
Label(framer,text='on the framer2',bg='yellow').pack()
Label(framer,text='on the framer3',bg='yellow').pack()
window.mainloop( )
⑫messagebox:消息框
使用消息框之前需要首先定义一个触发器,来触发这个弹窗,比如button按钮,通过触发器触发,调用messagebox,这样点击button按钮就可以弹出该对话框。下面给出messageBox提示信息的
messagebox提示信息的几种形式
messagebox.showinfo(title='Hi',message='你好!') #提示 messagebox.showwarning(title='Hi',message='警告!')#警告 messagebox.showerror(title='Hi',message='错误!') #错误 print(messagebox.askquestion(title='Hi',message='你好!'))#选择对话框,返回值为'yes'或'no' print(messagebox.askyesno(title='Hi',message='你好!'))#返回True和False print(messagebox.askokcancel(title='Hi',message='你好!'))#返回True和False
不管什么messagebox,最常用的方式是给一个title和message参数,分别标识题目和内容
案例:
from tkinter import *
from tkinter import messagebox
window=Tk()
window.title('My Window')
window.geometry('300x500')
def hit_me():
messagebox.showinfo(title='Hi',message='你好')
Button(window,text='hit me',bg='green',font=('Arial',12)
,command=hit_me).pack()
window.mainloop()
⑬部件部署方法:pack/grid/place
可以用这三种方法在窗口中指定位置处部署某个部件
1)grid
grid是方格,所有的内容都会被放置在这些方格中。例如:
from tkinter import *
window=Tk()
window.title('My Window')
window.geometry('300x500')
for i in range(3):
for j in range(3):
Label(window,text=1).grid(row=i,column=j,padx=10,pady=10,ipadx=10,ipady=10)
window.mainloop()
2)pack
pack方法按照上下左右的方式进行排列,具体位置通过输入参数side的值实现
from tkinter import *
window=Tk()
window.title('My Window')
window.geometry('300x500')
Label(window,text='p',fg='red').pack(side='top')
Label(window,text='p',fg='red').pack(side='bottom')
Label(window,text='p',fg='red').pack(side='left')
Label(window,text='p',fg='red').pack(side='right')
window.mainloop()
3)place
根据精确的坐标位置来定位,例如
Label(window,text='P1',font=('Arial',20)).place(x=50,y=100,anchor='nw')
就是将该部件放置在坐标为(x=50,y=100)的位置处,而参数anchor表示锚点位置(即原点位置)
⑭Combobox:下拉组合框
使用前要先从tkinter.ttk导入
from tkinter import * from tkinter.ttk import * window=Tk() window.title('My window') window.geometry('500x300') combo=Combobox(window) combo['values']=(1,2,3,4,5,'Text') combo.current(1) combo.pack() window.mainloop()
current方法用以设置默认显示的数值
如果要提取被选中的项,可以通过get方法——combo.get()
⑮ScrolledText:滚动条文本框,(超出范围时可以上下拖动滚动条)
使用前要先从tkinter.scrolledtext中导入
from tkinter import scrolledtext as st from tkinter import Tk window=Tk() window.title('My window') window.geometry('500x300') txt=st.ScrolledText(window,width=40,height=10) #需要指定文本区的长宽,否则会占据整个窗口 txt.pack() window.mainloop()
还有另外两个实用方法:insert与delete
txt.insert(INSERT,'Text') #插入 txt.delete(1.0,END)#删除
⑯Spinbox:可选输入控件
spin = Spinbox(window , from_= 0 , to = 100 , width = 5)
通过from_与to指定范围,width指定控件宽度
from tkinter import Spinbox,Tk window=Tk() window.title('My window') window.geometry('500x300') spin=Spinbox(window,from_=0,to=100) spin.pack() window.mainloop()
⑰Progressbar:进度条
要从tkinter.ttk导入
进度条值的设置:bar['value']
通过动态设置该值,就可以实现动态进度条的功能了
from tkinter import Tk,ttk from tkinter.ttk import Progressbar window=Tk() window.title('My window') window.geometry('500x300') style=ttk.Style() style.theme_use('default') style.configure('black.Horizontal.TProgressbar',background='black') bar=Progressbar(window,length=200,style='black.Horizontal.TProgressbar') bar['value']=70 bar.pack() window.mainloop()
⑱filedialog:文件对话框
1)创建文件对话框,选择文件并保存路径
from tkinter import filedialog file=filedialog.askopenfilename()
askopenfilename():选择一个并打开后,file变量会保存该文件的路径。
如果想一次选择多个文件并打开,我们可以用askopenfilenames:
files= filediaglog.askopenfilenames()
指定文件类型:参数filetypes;只需要在元组中指定扩展名即可。
file = filedialog.askopenfilename( filetypes = (('Text files','*.txt'),('all files','*')))
askdirectory():打开目录
指定初始目录:参数initialdir
下边的代码,展示了文件对话框与按钮组合的情况,是一种很常见的方式:
def clicked(): file=filedialog.askopenfilenames(initialdir=os.path.dirname(__file__)) btn=Button(window,text='打开文件夹',command=clicked)
⑲⑳
⑭综合,用户登录窗口的例子
编写一个用户登录界面,用户可以登录账户信息,如果账户已经存在,可以直接登录,登录名或者登录密码输入错误时会提示,如果账户不存在,则提示用户注册,点击注册进去注册界面,输入注册信息,确定后便返回登录界面进行登录
from tkinter import * from tkinter import messagebox import pickle window=Tk() window.title('Welcome to my first tkinter program!') window.geometry('400x300') #加载welcome image canvas=Canvas(window,width=400,height=135,bg='green') image_file=PhotoImage(file='Squirrel.png') image=canvas.create_image(200,0,anchor='n',image=image_file) canvas.pack(side='top') Label(window,text='Welcome',font=('Arial',16)).pack() #用户信息 Label(window,text='Username:',font=('Arial',14)).place(x=10,y=170) Label(window,text='Password:',font=('Arial',14)).place(x=10,y=210) #用户登录输入框 var_usr_name=StringVar() var_usr_name.set('example@python.com') entry_usr_name=Entry(window,textvariable=var_usr_name,font=('Arial',14)) entry_usr_name.place(x=120,y=175) #密码 var_usr_pwd=StringVar() entry_usr_pwd=Entry(window,textvariable=var_usr_pwd,font=('Arial',14),show='*') entry_usr_pwd.place(x=120,y=215) #定义用户登录功能 def usr_login(): #下边两行代码就是获取用户输入的username和password usr_name=var_usr_name.get() usr_pwd=var_usr_pwd.get() #设置异常捕获,当我们第一次访问用户信息文件时是不存在的,所以之而立设置异常捕获 try: with open('usrs_info.pickle','rb') as usr_file: usrs_info=pickle.load(usr_file) except FileNotFoundError: #这里是当我们没有读取到usr_file时候,程序会创建一个usr_file的文件 #并且将管理员的用户和密码输入,即用户名和密码均为'admin' with open('usrs_info.pickle','wb')as usr_file: usrs_info={'admin':'admin'} pickle.dump(usrs_info,usr_file) if usr_name in usrs_info: if usr_pwd == usrs_info[usr_name]: messagebox.showinfo(title='Welcome',message='How are you? '+usr_name) else: messagebox.showerror(message='Error,your password is wrond,try again.') else: is_sign_up=messagebox.askyesno('Welcome!','You have not signed up yet. Sign up please!') if is_sign_up: usr_sign_up() def usr_sign_up(): def sign_to_Le_Website(): #以下三行就是获取我们注册时候输入的信息 np=new_pwd.get() npf=new_pwd_confirm.get() nn=new_name.get() #打开我们记录数据的文件,将注册信息读出 with open('usrs_info.pickle','rb') as usr_file: exist_usr_info=pickle.load(usr_file) #判断两次密码是否输入一致 if np!=npf: messagebox.showerror('Error','Password and confirm password must be the same') #如果用户名已经在我们的数据文件中,则提示Error,用户已注册 elif nn in exist_usr_info: messagebox.showerror('Error','The user has already signed up!') #输入正确时 else: exist_usr_info[nn]=np with open('usrs_info.pickle','wb') as usr_file: pickle.dump(exist_usr_info,usr_file) messagebox.showinfo('Welcome','You have successfully signed up!') window_sign_up.destroy() window_sign_up=Toplevel(window) window_sign_up.geometry('300x200') window_sign_up.title('Sign up window') new_name=StringVar() new_name.set('example@python.com') Label(window_sign_up,text='Username:').place(x=10,y=10) entry_new_name=Entry(window_sign_up,textvariable=new_name) entry_new_name.place(x=130,y=10) new_pwd=StringVar() Label(window_sign_up,text='Password:').place(x=10,y=50) entry_usr_pwd_confirm=Entry(window_sign_up,textvariable=new_pwd,show='*') entry_usr_pwd_confirm.place(x=130,y=50) new_pwd_confirm=StringVar() Label(window_sign_up,text='Confirm Password:').place(x=10,y=90) entry_usr_pwd_confirm=Entry(window_sign_up,textvariable=new_pwd_confirm,show='*') entry_usr_pwd_confirm.place(x=130,y=90) btn_confirm_sign_up=Button(window_sign_up,text='Sign up',command=sign_to_Le_Website) btn_confirm_sign_up.place(x=180,y=120) #login和sign up按钮 btn_login=Button(window,text='Login',command=usr_login) btn_login.place(x=120,y=240) btn_sign_up=Button(window,text='Sign up',command=usr_sign_up) btn_sign_up.place(x=200,y=240) window.mainloop()
补充:
StringVar变量值的获取:var.get();设置:var.set('xxx')
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性