一,公共知识
1.第一个小程序(参考)
from tkinter import *
from tkinter import messagebox
def songhua(e): # e为事件对象
messagebox.showinfo("Message","给你一朵小红花")#窗口标题+显示信息
print("送花")
#1.创建主窗口对象
root = Tk()
root.title("我的第一个GUI程序")
#调整主窗口位置和大小
root.geometry("500x300+100+200")#窗口500*300大小,相对显示屏幕左上角,距离左边100像素,上面200
#2.在窗口中放置组件,创建按键控件
btn1 = Button(root)
btn1["text"] = "演示点击"
#3.调用布局管理器
btn1.pack() #压缩
#4.进行事件绑定
btn1.bind("<Button-1>",songhua)
#进入窗口事件循环
root.mainloop()
2.类对象方式创建窗口(推荐该方式)
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
self.btn1 =Button(self)
self.btn1["text"] = "点击送花"
self.btn1.pack()
self.btn1["command"] = self.songhua
#创建退出按钮
self.btn_quit = Button(self,text = "退出程序",command = self.master.destroy)
self.btn_quit.pack()
def songhua(self):
messagebox.showinfo("送花","送你99朵花")
root = Tk()
root.geometry("400x100+100+300")
root.title("一个经典的gui程序类")
app = Application(master = root)
root.mainloop()
3.三种控件布局方式
(1)pack布局
"""
tkinter中提供的布局管理器有三种:pack(水平/垂直排列),grid(网格排列),place(像素位置部署,更精确)
一,grid布局
采用表格结构组织组件,子组件位置由行和列的单元格来确定,并且可以跨行和跨列。
选项 说明 取值范围
column 单元格列号 从0开始的正整数
colunmspan 跨越的列数 正整数
row 单元格行号 从0开始的正整数
rowspan 跨越的行数 正整数
ipadx,ipady 设置子组件之间的间隔 非负浮点数,默认0.0
x/y方向,单位为像素
padx,pady 与之并列的组件之间的间隔 非负浮点数,默认0.0
x/y方向,单位为像素
sticky 组件紧贴所在单元格的某一角 n,s,w,e,nw,sw,se,ne,center(默认)
"""
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
self.label1 = Label(self,text = "用户名")
self.label1.grid(row = 0,column = 0)
self.entry1 = Entry(self)
self.entry1.grid(row = 0,column = 1)
Label(self,text = "用户名为手机号").grid(row = 0,column = 2)
Label(self,text = "密码").grid(row = 1,column = 0)
Entry(self,show = "*").grid(row = 1,column = 1)
Button(self,text = "登录").grid(row = 2,column = 1,sticky = EW)
Button(self,text = "取消").grid(row = 2,column = 2,sticky = E)
root = Tk()
root.geometry("400x400+100+300")
app = Application(master = root)
root.mainloop()
(2)grid布局
"""
二,pack布局管理器
按照垂直或者水平的方向自然排布,默认为在父组件中自顶向下垂直添加组件。
选项 说明 取值范围
side 定义组件靠在父组件的哪一边上 top,botton.left.right,默认为top
ipadx,ipady 设置子组件之间的间隔 非负浮点数,默认0.0
x/y方向,单位为像素
padx,pady 与之并列的组件之间的间隔 非负浮点数,默认0.0
x/y方向,单位为像素
anchor 对齐方式(w--左对齐,e--右对齐,n--顶对齐,s--底对齐) n,s,w,e,nw,sw,se,ne,center(默认)
"""
from tkinter import *
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
f1 = Frame(self)
f1.pack()
f2 = Frame(self).pack()
btnText = ["流行风","中国风","日本风","重金属","轻音乐"]
for txt in btnText:
Button(f1,text = txt).pack(side = "left",padx = "10") #水平排列
for i in range(1,20):
Label(f2,width = 5,height = 10,borderwidth = 1,relief = "solid",bg = "black" if i%2 ==0 else "white").pack(side = "left",padx = 2)
root = Tk()
root.geometry("700x220")
app = Application(master = root)
root.mainloop()
(3)place布局(感觉不太好用)
"""
三,place布局管理器
通过坐标精确控制组件的位置,适用于一些布局更加灵活的场景。
选项 说明 取值范围
x,y 组件左上角相对于窗口的绝对位置 非负整数
relx,rely 组件最上角相对于父组件的相对位置 relx:0--最左边,0.5--正中间,1--最右边
rely:0--最上边,0.5--正中间,1--最下边
relwidth,relheight 组件的宽度和高度(相对于父容器) 非负整数
anchor 对齐方式(w--左对齐,e--右对齐,n--顶对齐,s--底对齐) n,s,w,e,nw,sw,se,ne,center(默认)
"""
from tkinter import *
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack(fill="both", expand=True)
self.creatWidget()
def creatWidget(self):
"""创建组件"""
f1 = Frame(self,width = 200,height = 200,bg = "green")
# f1.pack()
f1.place(x = 30,y = 30) #失灵不知道因为什么,以后再说吧
Button(self,text = "你好吗").place(relx = 0.2,x = 100,y = 20,relwidth = 0.2,relheight = 0.5)
Button(f1,text = "你真的很好").place(relx = 0.6,rely = 0.7)
Button(f1,text = "你的老师").place(relx = 0.5,rely = 0.2)
root = Tk()
root.geometry("500x300")
root.title("布局管理器place")
root["bg"] = "white"
app = Application(master = root)
root.mainloop()
4.多种控件事件绑定方式
"""
一,通过组件对象绑定
1.通过command属性绑定(适合简单不需要获取event的对象) Button(root,text = "登录",command = login)
2.通过bind()方法绑定 c1= Canvas();c1.bind("<Button-1>",drawLine)
二,组件类的绑定
1.调用对象的bind_class 函数,将同类组件都绑定上事件 btn1.bind_class("Button","<Button-1>",func)
"""
from tkinter import *
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def mouseTest1(self,event):
print("bind()方式绑定,可以获取event对象")
print(event.widget)
def mouseTest2(self, a,b):
print("a = {0},b = {1}".format(a,b))
print("command方式绑定,不能直接获取event对象")
def mouseTest3(self,event):
print("右键单击事件,绑定所有的按钮控件")
print(event.widget)
def creatWidget(self):
"""创建组件"""
b1 = Button(self,text = "测试bind方法")
b1.pack(side = "left")
b1.bind("<Button-1>",self.mouseTest1)
b2 = Button(self,text = "测试command方法",command = lambda : self.mouseTest2("songjian","guo"))
b2.pack(side = "left")
# self.bind_class("Button","<Button-3>",self.mouseTest3) #感觉这种方式并不好
b1.bind_class("Button", "<Button-3>", self.mouseTest3)
root = Tk()
root.geometry("270x50")
app = Application(master = root)
root.mainloop()
5.常见事件学习
"""
所有的组件都可以通过 组件.bind(event,handler) 的方式来绑定事件
鼠标和键盘事件
代码 说明
<Button-1> 鼠标左键按下,2表示中键,3表示右键
<ButtonPress-1>
<1>
<ButtonRelease-1> 鼠标左键释放
<B1-Motion> 按住鼠标左键移动
<Double-Button-1> 双击左键
<Enter> 鼠标指针进入某一组件区域
<Leave> 鼠标指针离开某一组件区域
<MouseWheet> 滚动滚轮
<KeyPress-a> 按下a键,a可用其他键代替
<KeyRelease-a> 释放a键
<KeyPress-A> 按下A键,可用其他代替
<Alt-KeyPress-a> 同事按下alt和a,alt可用ctrl和shift替代
<Double-KeyPress-a> 快速按下两下a
<Control-V> 同时按下CTRL和V键,V可以被替代
常用event对象属性
名称 说明
char 按键字符,仅对键盘事件有效
keycode 按键编码,仅对键盘事件有效
keysym 按键名称,仅对键盘事件有效(在系统中的代表名)
num 鼠标按键,仅对鼠标事件有效
type 所触发的事件类型
widget 引发事件的组件
width,height 组件改变后的大小,仅Configure有效
x,y 鼠标当前位置,相对于父容器
x_root,y_root 鼠标当前位置,相对于整个屏幕
"""
from tkinter import *
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def mouseTest(self,event):
print("鼠标左键单击位置(相对于父容器):{0},{1}".format(event.x,event.y))
print("鼠标左键单击位置(相对于屏幕):{0},{1}".format(event.x_root,event.y_root))
print("事件绑定的组件:{0}".format(event.widget))
def testDrag(self,event):
self.c1.create_oval(event.x,event.y,event.x+1,event.y+1)
def keyboardTest(self,event):
print("键的keycode:{0},键的char:{1},键的keysym{2}".format(event.keycode,event.char,event.keysym))
def press_a_test(self,event):
print("press a")
def release_a_test(self,event):
print("release a")
def creatWidget(self):
"""创建组件"""
self.c1 = Canvas(self,width = 200,height = 200,bg = "green")
self.c1.pack()
self.c1.bind("<Button-1>",self.mouseTest)
self.c1.bind("<B1-Motion>",self.testDrag)
self.master.bind("<KeyPress>",self.keyboardTest) #self.master 才能代表root
self.master.bind("<KeyPress-a>",self.press_a_test)
self.master.bind("<KeyRelease-a>",self.release_a_test)
root = Tk()
root.geometry("530x300")
app = Application(master = root)
root.mainloop()
6.通过 lambda 给处理函数传参
from tkinter import *
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def mouseTest1(self):
print("command方式,简单情况:不设置获取event对象,可以使用")
def mouseTest2(self, a,b):
print("a = {0},b = {1}".format(a,b))
def creatWidget(self):
"""创建组件"""
Button(self,text = "测试command1",command = self.mouseTest1).pack(side = "left")
Button(self, text="测试command2", command=lambda: self.mouseTest2("songjian","guo")).pack(side="left")
root = Tk()
root.geometry("270x50")
app = Application(master = root)
root.mainloop()
二,控件学习
1.常用组件汇总
2.常见组件Option选项(设置方法/常见参数)
"""
option选项的三种设置方式
1.创建对象是,使用命名参数设置
new = Button(self,fg = "red",bg = "blue")
2.创建对象后,使用字典索引形式设置
new["fg"] = "red"
3.创建对象后,使用config()方法设置
new.config(fg = "red",bg = "blue")
option选项
activebackground--指定组件处于激活状态时的背景色
activeforeground--指定组件处于激活状态时的前景色
anchor--指定组件内内容的显示位置:N,NE,E,SE,S,SW,W,NW,CENTER.比如:NW(North West)
background(gd)--指定组件正常显示时的背景色
bitmap--指定在组件上显示该选型指定的位图
borderwidth--指定组件显示3D边框的宽度
cursor--指定光标在组件上的样式
command--指定组件相关联的命令方法
font--指定组件上显示的文本字体
foreground(fg)--指定组件正常显示时的前景色
highlightbackground--指定组件在高亮状态下的背景色
highlightcolor--指定组件在高亮状态下的前景色
highlightthickness--指定组件在高亮状态下的周围方形区域的宽度
height--指定组件高度,至少为1
image--指定组件中显示的图像,其会覆盖text,bitmap选项指定的内容
justify--指定组件内部内容的对齐方式:LEFT(左对齐),CENTER(居中对齐),RIGHT(右对齐)
padx--指定组件内部在水平方向上两边的空白
pady--指定组件内部在垂直方向上两边的空白
relief--指定组件的3D效果,该选项支持的值包括RAISED,SUNKEN,FLAT,RIDGE,SOLID,GROOVE
该值指出组件内部相对于外部的外观样式。比如RAISED表示组件内部相对于外部凸起
selectbackground--指定组件在选中状态下的背景色
selectborderwidth--指定组件在选中状态下的3D边框宽度
selectforeground--指定组件在选中状态下的前景色
state--指定组件的当前状态。NORMAL(正常),DISABLE(禁用)
takefocus--指定组件在键盘遍历(Tab或Shift+Tab)时是否接收焦点,1--接收焦点 0--不接收焦点
text--指定组件上显示的文本
textvariable--指定一个变量名,通过该属性获得组件字符内容
underline--指定为组件文本的第几个字符添加下划线,该选项就相当于为组件绑定了快捷键
width--指定组件宽度,至少为1
wraplength--对于能支持字符换行的组件,该选项指定每行显示的最大字符数,
超过该数量的字符将会转到下行显示
xscrollcommand--通常用于将组件的水平滚动改变(包括内容滚动或高度发生改变)
与水平滚动条的set方法关联。从而让组件的水平滚动改变传递到水平滚动条
yscrollcommand--通常用于将组件的垂直滚动改变(包括内容滚动或高度发生改变)
与垂直滚动条的set方法关联。从而让组件的垂直滚动改变传递到垂直滚动条
"""
3.Lbel控件(信息展示)
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
self.label1 = Label(self,text = "Label测试",width = 10,height = 2,bg = "black",fg = "white")
# self.label1["text"] = "Label测试"
self.label1.pack()
#字体调整
self.label2 = Label(self,text = "字体测试",width = 10,height = 2,bg = "blue",fg = "white",font = ("黑体",30))
self.label2.pack()
#显示图片,只能显示gif格式的图片
global photo #如果为局部变量,则会在循环事件中被销毁
photo = PhotoImage(file = "图片1.gif")
self.label3 = Label(self,text = "图片显示",image = photo)
self.label3.pack()
#显示多行文本
self.label4 = Label(self,text = "多行文本1\n多行文本2\n多行文本3\n",borderwidth = 1,relief = "solid",justify = "right")
self.label4.pack()
def songhua(self):
messagebox.showinfo("送花","送你99朵花")
root = Tk()
root.geometry("400x400+100+300")
root.title("测试Label")
app = Application(master = root)
root.mainloop()
4.Button控件(按钮)
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
self.btn1 = Button(self,text = "登录",width = 6,height = 3,anchor = E,command = self.login)
self.btn1.pack()
global photo
photo = PhotoImage(file = "图片1.gif")
self.btn2 = Button(self,image = photo,command = self.login)
self.btn2.pack()
# self.btn2.config(state = "disabled")#设置为不可用
def login(self):
messagebox.showinfo("送花","送你99朵花")
root = Tk()
root.geometry("400x400+100+300")
root.title("测试Button")
app = Application(master = root)
root.mainloop()
5.Entry控件(单行文本框)
"""
Entry用来接收一行字符串的控件,如果用户输入的文字长度长于Entry控件
的宽度时,文字会自动向后滚动,如果想输入多行文本,需要使用Text控件。
"""
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
self.label1 = Label(self,text = "用户名")
self.label1.pack()
v1 = StringVar() #BooleanVar IntVar DoubleVar StringVar
self.entry1 = Entry(self,textvariable = v1)#将控件属性与变量关联起来
self.entry1.pack()
######################
#获取信息
# v1.set("admin")
# print(v1.get())
# print(self.entry1.get())
######################
self.label2 = Label(self,text = "密码")
self.label2.pack()
v2 = StringVar() #BooleanVar IntVar DoubleVar StringVar
self.entry2 = Entry(self,textvariable = v2,show = "*")#输入密码时显示为*,但获取到的真实值不变
self.entry2.pack()
# Button(self,text = "登录",command = self.login).pack()
self.btn1 = Button(self,text = "登录",command = self.login)
self.btn1.pack()
def login(self):
print("输入的用户名为" + self.entry1.get())
print("输入的密码为" + self.entry2.get())
messagebox.showinfo("送花","送你99朵花")
root = Tk()
root.geometry("400x400+100+300")
root.title("测试Entry")
app = Application(master = root)
root.mainloop()
6.Text控件(多行文本框)
"""
Text主要用于显示多行文本,还可以显示网页连接,图片,HTML页面,CSS样式表。
常被用作简单的文本处理器,文本编辑器或者网页浏览器。
"""
from tkinter import *
from tkinter import messagebox
import webbrowser
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
self.w1 = Text(root,width = 40,height = 12,bg = "gray")
#宽度20个字母(10个汉字),高度为一个行高
self.w1.pack()
self.w1.insert(1.0,"0123456789\nabcdefg") #从第一行第0列开始输入
self.w1.insert(2.3,"锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦\n")#从第二行第3列开始插入,覆盖了原有文本数据
Button(self,text = "重复插入文本",command = self.insertText).pack(side = "left")
Button(self, text="返回文本", command=self.returnText).pack(side="left")
Button(self, text="添加图片", command=self.addImage).pack(side="left")
Button(self, text="添加组件", command=self.addWidget).pack(side="left")
Button(self, text="通过tag精准控制文本", command=self.testTag).pack(side="left")
def insertText(self):
#INSERT索引表示在光标处插入
self.w1.insert(INSERT,"gaoqi")
#END索引表示在最后插入
self.w1.insert(END,"[sxt]")
def returnText(self):
#Indexes(索引)是用来指向Text组件中文本的位置,Text的组件索引也是对应实际字符之间的位置。
#核心:行号1开始,列号0开始
print(self.w1.get(1.2,1.6))#获取第一行2-6列文本
# self.w1.insert(1.8,"gaoqi")
print("所有文本内容:\n" + self.w1.get(1.0,END))#第一行0列,到最后,就是获取所有文本内容
def addImage(self):
# global photo
self.photo = PhotoImage(file = "图片1.gif")
self.w1.image_create(END,image = self.photo)
def addWidget(self):
b1 = Button(self.w1,text = "建国学堂")
#在text创建组件的命令
self.w1.window_create(INSERT,window = b1)
def testTag(self):
self.w1.delete(1.0,END)
self.w1.insert(INSERT,"good good study,day day up\ngood潍坊建国学堂\n霸占程序员\n百度,搜一下你就知道")
self.w1.tag_add("good",1.0,1.9) #增加一个标记,名字叫good,区域为第一行0-9
self.w1.tag_config("good",background = "yellow",foreground = "red")
self.w1.tag_add("baidu",4.0,4.2)#增加一个标记区域
self.w1.tag_config("baidu",underline = True) #将区域加下划线
self.w1.tag_bind("baidu","<Button-1>",self.webshow) #调用默认浏览器打开网页
def webshow(self,event):
webbrowser.open("http://www.baidu.com")
root = Tk()
root.geometry("400x400+100+300")
root.title("测试Text")
app = Application(master = root)
root.mainloop()
7.Radiobutton控件(组单选按钮)
"""
Entry用来接收一行字符串的控件,如果用户输入的文字长度长于Entry控件
的宽度时,文字会自动向后滚动,如果想输入多行文本,需要使用Text控件。
"""
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
self.v = StringVar()
self.v.set("F") #默认选中女生
self.r1 = Radiobutton(self,text = "男性",value = "M",variable = self.v)
self.r2 = Radiobutton(self,text = "女性",value = "F",variable = self.v)
self.r1.pack(side = "left")
self.r2.pack(side = "left")
Button(self,text = "确定",command = self.confirm).pack(side = "left")
def confirm(self):
messagebox.showinfo("测试","选择的性别为:" + self.v.get())
root = Tk()
root.geometry("400x400+100+300")
app = Application(master = root)
root.mainloop()
8.Checkbutton控件(组复现按钮)
"""
Entry用来接收一行字符串的控件,如果用户输入的文字长度长于Entry控件
的宽度时,文字会自动向后滚动,如果想输入多行文本,需要使用Text控件。
"""
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
self.codeHobby = IntVar()
self.videoHobby = IntVar()
print(self.codeHobby.get()) #默认是0
self.c1 = Checkbutton(self,text = "敲代码",variable = self.codeHobby,onvalue = 1,offvalue = 0) #选中返回1,不选中返回0
self.c2 = Checkbutton(self,text = "看视频",variable = self.videoHobby,onvalue = 1,offvalue = 0)
self.c1.pack(side = "left")
self.c2.pack(side = "left")
Button(self,text = "确定",command = self.confirm).pack(side = "left")
def confirm(self):
if self.videoHobby.get() == 1:
messagebox.showinfo("测试","选择了看视频")
if self.codeHobby.get() == 1:
messagebox.showinfo("测试","选择了敲代码")
root = Tk()
root.geometry("400x400+100+300")
app = Application(master = root)
root.mainloop()
9.Optionmenu控件(菜单选项)
from tkinter import *
root = Tk()
root.geometry("200x100")
v = StringVar(root)
v.set("打开查看选项")
om = OptionMenu(root,v,"选项一","选项二","选项三")
om["width"] = 10
om.pack()
def test1():
print("选择的选型为:",v.get())
Button(root,text = "确定",command = test1).pack()
root.mainloop()
10.Scale控件(滑块)
from tkinter import *
root = Tk()
root.geometry("400x150")
def test1(value):
print("滑块的值:",value)
newFont = ("宋体",value)
a.config(font = newFont)
s1 = Scale(root,from_ = 10,to = 50,length = 200,tickinterval = 5,orient = HORIZONTAL,command = test1) #orient = HORIZONTA改为水平
s1.pack()
a = Label(root,text = "好好学习",width = 10,height = 1,bg = "black",fg = "white")
a.pack()
root.mainloop()
11.Askcolor控件(颜色选择框)
from tkinter import *
from tkinter.colorchooser import *
root = Tk()
root.geometry("400x150")
def test1():
s1 = askcolor(color = "red",title = "选择背景色")
print(s1)
#((227.88671875, 207.80859375, 28.109375), '#e3cf1c')
root.config(bg = s1[1])
Button(root,text = "选择背景色",command =test1).pack()
root.mainloop()
12.弹出消息框控件
"""
一,简单消息框
simpledialog(简单对话框)包含以下函数
函数名 说明
askfloat(title,prompt,**kw) 输入并返回浮点数
askinteger(title,prompt,**kw) 输入并返回整数
askstring(title,prompt,**kw) 输入并返回字符串
title--窗口标题 prompt--提示信息 kw为各种选项:initialvalue(初始值),minvalue(最小值),maxvalue(最大值)
"""
from tkinter.simpledialog import *
root = Tk()
root.geometry("400x100")
def test1():
a = askinteger(title = "输入年龄",prompt="请输入年龄",initialvalue = 18,minvalue = 1,maxvalue = 150)
show["text"] = a
Button(root,text = "选择文本文件",command =test1).pack()
show = Label(root,width = 40,height = 3,bg = "green")
show.pack()
root.mainloop()
"""
二,通用消息框
"""
from tkinter import *
from tkinter.messagebox import *
root = Tk()
root.geometry("400x100")
a1 = showinfo(title="宋建国", message="好好学习,天天洗脚\就是浪") # 各种状态的框太多了,用的时候再查
print(a1) # ok
root.mainloop()
13.文件对话框(文件操作)
""""
帮助我们实现可视化的操作目录,文件。
函数名 对话框 说明
askopenfilename(**options) 文件对话框 返回打开的文件名
askopenfilenames(**options) 文件对话框 返回打开的多个文件名列表
askopenfile(**options) 文件对话框 返回打开文件对象
askopenfiles(**options) 文件对话框 返回打开的文件对象列表
askdirectory(**options) 目录对话框 返回目录名
asksaveasfile(**options) 保存对话框 返回保存的文件对象
asksaveasfilename(**options) 保存对话框 返回保存的文件名
options
参数名 说明
defaultextension 默认后缀,没有输入则自动添加
filetypes = [(label1,pattern1),(label2,pattern2)] 文件显示过滤器
initaldir 初始目录
initalfile 初始文件
parent 父窗口
title 窗口标题
"""
###########################################返回要打开的文件名#########################################################
from tkinter import *
from tkinter.filedialog import *
root = Tk()
root.geometry("400x100")
def test1():
f = askopenfilename(title = "上传文件",initialdir = "C:/Users/Administrator/Desktop/Tkinter/尚学堂",filetypes = [("图片文件",".gif")])
show["text"] = f
Button(root,text = "选择图片",command =test1).pack()
show = Label(root,width = 40,height = 3,bg = "green")
show.pack()
root.mainloop()
####################################打开文件信息################################################################
from tkinter import *
from tkinter.filedialog import *
root = Tk()
root.geometry("400x100")
def test1():
f = askopenfile(title = "上传文件",initialdir = "d:",filetypes = [("文本文件",".txt")])
show["text"] = f.read() #可能会遇到文字编码问题,结合python文件读取使用
Button(root,text = "选择文本文件",command =test1).pack()
show = Label(root,width = 40,height = 3,bg = "green")
show.pack()
root.mainloop()
三,项目知识深化
1.【案例一】计算器界面实现
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.pack()
self.creatWidget()
def creatWidget(self):
"""创建组件"""
btnText = (
("MC","M+","M-","MR"),
("C","±","/","x"),
(7,8,9,"-"),
(4,5,6,"+"),
(1,2,3,"="),
(0,".")
)
Entry(self).grid(row = 0,column = 0,columnspan = 4,pady = 10)
for rindex,r in enumerate(btnText):
for cindex,c in enumerate(r):
#单独处理0和等号
if c == "=":
Button(self,text = c,width = 2).grid(row = rindex+1,column = cindex,rowspan = 2,sticky = NSEW)
elif c == 0:
Button(self,text = c,width = 2).grid(row = rindex+1,columnspan = 2,column = cindex,sticky = NSEW)
elif c == ".":
Button(self,text = c,width = 2).grid(row = rindex+1,column = cindex+1,sticky = NSEW)
else:
Button(self,text = c,width = 2).grid(row = rindex+1,column = cindex,sticky = NSEW)
root = Tk()
root.geometry("200x250+200+300")
app = Application(master = root)
root.mainloop()
2.【案例二】菜单界面实现
from tkinter.filedialog import *
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.textpad = None
self.pack()
self.creatWidget()
def creatWidget(self):
#创建主菜单栏
menubar = Menu(root)
#创建子菜单
menuFile = Menu(menubar)
menuEdit = Menu(menubar)
menuHelp = Menu(menubar)
#将子菜单加入到主菜单栏
menubar.add_cascade(label = "文件(F)",menu = menuFile)
menubar.add_cascade(label="编辑(E)", menu=menuEdit)
menubar.add_cascade(label="帮助(H)", menu=menuHelp)
#添加菜单项
menuFile.add_command(label = "新建",accelerator = "ctrl+n",command = self.test)
menuFile.add_command(label="打开", accelerator="ctrl+o", command=self.test)
menuFile.add_command(label="保存", accelerator="ctrl+s", command=self.test)
menuFile.add_separator()
menuFile.add_command(label = "退出",accelerator = "strl+q",command = self.test)
#将菜单栏添加到根窗口
root["menu"] = menubar
#文本编辑区
self.textpad = Text(root,width = 50,height = 30)
self.textpad.pack()
#创建上下菜单
self.contextMenu = Menu(root)
self.contextMenu.add_command(label = "背景颜色",command = self.test)
#为右键绑定事件
root.bind("<Button-3>",self.createContextMenu)
def test(self):
pass
def createContextMenu(self,event):
#菜单在鼠标右键单击的坐标处显示
self.contextMenu.post(event.x_root,event.y_root)
if __name__ == '__main__':
root = Tk()
root.geometry("450x300+200+300")
root.title("好好学习")
app = Application(master = root)
root.mainloop()
3.【案例三】记事本项目
#coding = utf-8
import tkinter as tk
from tkinter.filedialog import *
from tkinter.colorchooser import *
class Application(Frame):
def __init__(self,master = None):
super().__init__(master)
self.master = master
self.textpad = None
self.pack()
self.creatWidget()
def creatWidget(self):
#创建主菜单栏
menubar = Menu(self,tearoff = False)
#创建子菜单
menuFile = Menu(menubar,tearoff = False)
menuEdit = Menu(menubar,tearoff = False)
menuHelp = Menu(menubar,tearoff = False)
#将子菜单加入到主菜单栏
menubar.add_cascade(label = "文件(F)",menu = menuFile)
menubar.add_cascade(label="编辑(E)", menu=menuEdit)
menubar.add_cascade(label="帮助(H)", menu=menuHelp)
#添加菜单项
menuFile.add_command(label = "新建",accelerator = "ctrl+n",command = self.newfile)
menuFile.add_command(label="打开", accelerator="ctrl+o", command=self.openfile)
menuFile.add_command(label="保存", accelerator="ctrl+s", command=self.savefile)
menuFile.add_separator()
menuFile.add_command(label = "退出",accelerator = "strl+q",command = self.exit)
#将菜单栏添加到根窗口
self.master["menu"] = menubar
#增加选项对应快捷键
self.master.bind("<Control-n>",lambda event:self.newfile())
self.master.bind("<Control-o>",lambda event:self.openfile())
self.master.bind("<Control-s>", lambda event: self.savefile())
self.master.bind("<Control-q>", lambda event: self.quit())
#添加底部状态栏
status_str_var = tk.StringVar()
status_str_var.set("字符数{0}".format(0))
self.status_label = tk.Label(self,textvariable = status_str_var,bd = 1,relief = tk.SUNKEN,anchor = tk.W)
self.status_label.pack(side = tk.BOTTOM,fill = tk.X)
# #添加左侧行数栏
# var_line = tk.StringVar()
# self.line_label = tk.Label(self, textvariable=var_line,width = 1,bg = "#faebd7",anchor = tk.N,font = 10)
# self.line_label.pack(side=tk.LEFT, fill=tk.Y)
#文本编辑区
self.textpad = Text(self,width = 60,height = 30)
# self.textpad.pack(fill = tk.BOTH,expand = True)
self.textpad.pack()
#添加编辑滚动条
# self.scroll = tk.Scrollbar(self.textpad)
# self.textpad.config(yscrollcommand = self.scroll.set)
# self.scroll.config(command = self.textpad.yview)
# self.scroll.pack(side = tk.RIGHT,fill = tk.Y)
#创建上下菜单
self.contextMenu = Menu(self)
self.contextMenu.add_command(label = "背景颜色",command = self.bgColor)
#为右键绑定事件
self.master.bind("<Button-3>",self.createContextMenu)
def openfile(self):
self.textpad.delete("1.0","end") #把Text控件中所有内容清空,不清空会把所有显示的都写进去,就会重复
temp_filename = askopenfilename(title="打开文件")
try:
with open(temp_filename, encoding='utf-8') as f: #解决文本编码问题
# with askopenfile(title="打开文本文件") as f:
self.textpad.insert(INSERT,f.read())
self.filename = f.name
except:
print("文本格式发生错误")
with open(temp_filename) as f: #解决文本编码问题
# with askopenfile(title="打开文本文件") as f:
self.textpad.insert(INSERT,f.read())
self.filename = f.name
def savefile(self):
print(self.textpad.get(1.0,END))
with open(self.filename,"w") as f:
c = self.textpad.get(1.0,END) #获取所有文本内容
# f.seek(0) #重置指针到一开始的位置
f.write(c)
def newfile(self):
self.filename = asksaveasfilename(title = "另存为",initialfile = "未命名.txt",filetypes = [("文本文档","*.txt")],defaultextension = ".txt")
self.savefile()
def bgColor(self):
s1 = askcolor(color="red", title="选择背景色")
self.textpad.config(bg=s1[1])
def exit(self):
self.quit()
def createContextMenu(self,event):
#菜单在鼠标右键单击的坐标处显示
self.contextMenu.post(event.x_root,event.y_root)
if __name__ == '__main__':
root = Tk()
root.geometry("450x300+200+300")
root.title("好好学习")
app = Application(master = root)
root.mainloop()
4.【案例四】简单图片浏览器(实现jpg格式图片显示)
import tkinter as tk
import glob
from PIL import Image,ImageTk
root = tk.Tk()
root.geometry("900x650+100+100")
root.title("图片查看器")
photos = glob.glob("./input/*.jpg")
photos = [ImageTk.PhotoImage(Image.open(photo)) for photo in photos]
current_photo_no = 0
photo_label = tk.Label(root,image = photos[current_photo_no],width = 900,height = 600)
photo_label.pack()
number_var = tk.StringVar()
number_var.set("1 of 2") #可改,这里先定死
tk.Label(root,textvariable = number_var,bd = 1,relief = tk.SUNKEN,anchor = tk.CENTER).pack(fill = tk.X)#充满X框
button_frame = tk.Frame(root)
button_frame.pack()
prev_photo = tk.Button(button_frame,text = "上一页")
next_photo = tk.Button(button_frame,text = "下一页")
prev_photo.pack(side = tk.LEFT,anchor = tk.CENTER)
next_photo.pack(side = tk.RIGHT,anchor = tk.CENTER)
def change_photos(next_no):
global current_photo_no
current_photo_no += next_no
if current_photo_no >=len(photos):
current_photo_no = 0
if current_photo_no < 0:
current_photo_no = len(photos) - 1
number_var.set(f"{current_photo_no+1} of {len(photos)}")
photo_label.configure(image = photos[current_photo_no])
prev_photo.config(command = lambda : change_photos(-1))
next_photo.config(command = lambda : change_photos(1))
root.mainloop()