学习自:

Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) - 洪卫 - 博客园

Tkinter简明教程 - 知乎

TkDocs_官方文档

一个Tkinter库较为全面的总结,很细致!

一个在Tkinter中使用time实现界面快速刷新的例子

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()

测试效果:

python弄一个选择框 python选项框_消息框

 

 ②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:列表框

相关参数、方法:


主要方法:

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:可选输入控件

python弄一个选择框 python选项框_控件_02

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()

python弄一个选择框 python选项框_Text_03

 

 

⑱filedialog:文件对话框

1)创建文件对话框,选择文件并保存路径

from tkinter import filedialog
file=filedialog.askopenfilename()

python弄一个选择框 python选项框_python弄一个选择框_04

 

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')