前戏:老牌python GUI程序(Tkinter)
import tkinter.messagebox as messagebox class Application(Frame): def __init__(self,master=None): Frame.__init__(self,master,bg="red") #设置框架类的父类(基于master<主窗体>),frame可以是看做控件的父容器 self.pack() #显示frame控件 self.createWidgets() def createWidgets(self): #用于创建控件(是frame的子) self.nameInput = Entry(self) self.nameInput.pack() self.alertButton = Button(self,text="Hello",command=self.hello) self.alertButton.pack() def hello(self): name = self.nameInput.get() messagebox.showinfo("Message","Hello, %s"%name) root = Tk() root.title("标题") root.wm_minsize(200,200) app = Application(root) app.mainloop()
前置:各个参数了解:
tkinter模块常用参数(python3) 1、使用tkinter.Tk() 生成主窗口(root=tkinter.Tk()); root.title(‘标题名’) 修改框体的名字,也可在创建时使用className参数来命名; root.resizable(0,0) 框体大小可调性,分别表示x,y方向的可变性; root.geometry(‘250x150’)指定主框体大小; root.quit() 退出; root.update_idletasks() root.update() 刷新页面; 2、初级样例: import tkinter root=tkinter.Tk() #生成root主窗口 label=tkinter.Label(root,text=’Hello,GUI’) #生成标签 label.pack() #将标签添加到主窗口 button1=tkinter.Button(root,text=’Button1’) #生成button1 button1.pack(side=tkinter.LEFT) #将button1添加到root主窗口 button2=tkinter.Button(root,text=’Button2’) button2.pack(side=tkinter.RIGHT) root.mainloop() #进入消息循环(必需组件) 3、tkinter中的15种核心组件: Button 按钮; Canvas 绘图形组件,可以在其中绘制图形; Checkbutton 复选框; Entry 文本框(单行); Text 文本框(多行); Frame 框架,将几个组件组成一组 Label 标签,可以显示文字或图片; Listbox 列表框; Menu 菜单; Menubutton 它的功能完全可以使用Menu替代; Message 与Label组件类似,但是可以根据自身大小将文本换行; Radiobutton 单选框; Scale 滑块;允许通过滑块来设置一数字值 Scrollbar 滚动条;配合使用canvas, entry, listbox, and text窗口部件的标准滚动条; Toplevel 用来创建子窗口窗口组件。 (在Tkinter中窗口部件类没有分级;所有的窗口部件类在树中都是兄弟。) 4、组件的放置和排版(pack,grid,place) pack组件设置位置属性参数: after: 将组件置于其他组件之后; before: 将组件置于其他组件之前; anchor: 组件的对齐方式,顶对齐’n’,底对齐’s’,左’w’,右’e’ side: 组件在主窗口的位置,可以为’top’,’bottom’,’left’,’right’(使用时tkinter.TOP,tkinter.E); fill 填充方式 (Y,垂直,X,水平) expand 1可扩展,0不可扩展 grid组件使用行列的方法放置组件的位置,参数有: column: 组件所在的列起始位置; columnspam: 组件的列宽; row: 组件所在的行起始位置; rowspam: 组件的行宽; place组件可以直接使用坐标来放置组件,参数有: anchor: 组件对齐方式; x: 组件左上角的x坐标; y: 组件右上角的y坐标; relx: 组件相对于窗口的x坐标,应为0-1之间的小数; rely: 组件相对于窗口的y坐标,应为0-1之间的小数; width: 组件的宽度; heitht: 组件的高度; relwidth: 组件相对于窗口的宽度,0-1; relheight: 组件相对于窗口的高度,0-1; 5、使用tkinter.Button时控制按钮的参数: anchor: 指定按钮上文本的位置; background(bg): 指定按钮的背景色; bitmap: 指定按钮上显示的位图; borderwidth(bd):指定按钮边框的宽度; command: 指定按钮消息的回调函数; cursor: 指定鼠标移动到按钮上的指针样式; font: 指定按钮上文本的字体; foreground(fg):指定按钮的前景色; height: 指定按钮的高度; image: 指定按钮上显示的图片; state: 指定按钮的状态(disabled); text: 指定按钮上显示的文本; width: 指定按钮的宽度 padx 设置文本与按钮边框x的距离,还有pady; activeforeground按下时前景色 textvariable 可变文本,与StringVar等配合着用 6、文本框tkinter.Entry,tkinter.Text控制参数: background(bg) 文本框背景色; foreground(fg) 前景色; selectbackground选定文本背景色; selectforeground选定文本前景色; borderwidth(bd) 文本框边框宽度; font 字体; show 文本框显示的字符,若为*,表示文本框为密码框; state 状态; width 文本框宽度 textvariable 可变文本,与StringVar等配合着用 7、标签tkinter.Label组件控制参数: Anchor 标签中文本的位置; background(bg) 背景色; foreground(fg) 前景色; borderwidth(bd) 边框宽度; width 标签宽度; height 标签高度; bitmap 标签中的位图; font 字体; image 标签中的图片; justify 多行文本的对齐方式; text 标签中的文本,可以使用’\n’表示换行 textvariable 显示文本自动更新,与StringVar等配合着用 8、单选框和复选框Radiobutton,Checkbutton控制参数: anchor 文本位置; background(bg) 背景色; foreground(fg) 前景色; borderwidth 边框宽度; width 组件的宽度; height 组件高度; bitmap 组件中的位图; image 组件中的图片; font 字体; justify 组件中多行文本的对齐方式; text 指定组件的文本; value 指定组件被选中中关联变量的值; variable 指定组件所关联的变量; indicatoron 特殊控制参数,当为0时,组件会被绘制成按钮形式; textvariable 可变文本显示,与StringVar等配合着用 9、组图组件Canvas控制参数: background(bg) 背景色; foreground(fg) 前景色; borderwidth 组件边框宽度; width 组件宽度; height 高度; bitmap 位图; image 图片; 绘图的方法主要以下几种: create_arc 圆弧; create_bitmap 绘制位图,支持XBM; create_image 绘制图片,支持GIF(x,y,image,anchor); create_line 绘制支线; create_oval; 绘制椭圆; create_polygon 绘制多边形(坐标依次罗列,不用加括号,还有参数,fill,outline); create_rectangle 绘制矩形((a,b,c,d),值为左上角和右下角的坐标); create_text 绘制文字(字体参数font,); create_window 绘制窗口; delete 删除绘制的图形; itemconfig 修改图形属性,第一个参数为图形的ID,后边为想修改的参数; move 移动图像(1,4,0),1为图像对象,4为横移4像素,0为纵移像素,然后用root.update()刷新即可看到图像的移动,为了使多次移动变得可视,最好加上time.sleep()函数; 只要用create_方法画了一个图形,就会自动返回一个ID,创建一个图形时将它赋值给一个变量,需要ID时就可以使用这个变量名。 coords(ID) 返回对象的位置的两个坐标(4个数字元组); 对于按钮组件、菜单组件等可以在创建组件时通过command参数指定其事件处理函数。方法为bind;或者用bind_class方法进行类绑定,bind_all方法将所有组件事件绑定到事件响应函数上。 10、菜单Menu 参数: tearoff 分窗,0为在原窗,1为点击分为两个窗口 bg,fg 背景,前景 borderwidth 边框宽度 font 字体 activebackgound 点击时背景,同样有activeforeground,activeborderwidth,disabledforeground cursor postcommand selectcolor 选中时背景 takefocus title type relief 方法: menu.add_cascade 添加子选项 menu.add_command 添加命令(label参数为显示内容) menu.add_separator 添加分隔线 menu.add_checkbutton添加确认按钮 delete 删除 11、事件关联 bind(sequence,func,add)—— bind_class(className,sequence,func,add) bind_all(sequence,func,add) 事件参数: sequence 所绑定的事件; func 所绑定的事件处理函数; add 可选参数,为空字符或‘+’; className 所绑定的类; 鼠标键盘事件 鼠标左键按下,2表示中键,3表示右键; 同上; 鼠标左键释放; 按住鼠标左键移动; 双击左键; 鼠标指针进入某一组件区域; 鼠标指针离开某一组件区域; 滚动滚轮; 按下A键,A可用其他键替代; 同时按下alt和A;alt可用ctrl和shift替代; 快速按两下A; 大写状态下按A; 窗口事件 Activate 当组件由不可用转为可用时触发; Configure 当组件大小改变时触发; Deactivate 当组件由可用转变为不可用时触发; Destroy 当组件被销毁时触发; Expose 当组件从被遮挡状态中暴露出来时触发; Unmap 当组件由显示状态变为隐藏状态时触发; Map 当组件由隐藏状态变为显示状态时触发; FocusIn 当组件获得焦点时触发; FocusOut 当组件失去焦点时触发; Property 当窗体的属性被删除或改变时触发; Visibility 当组件变为可视状态时触发; 响应事件 event对象(def function(event)): char 按键字符,仅对键盘事件有效; keycode 按键名,仅对键盘事件有效; keysym 按键编码,仅对键盘事件有效; num 鼠标按键,仅对鼠标事件有效; type 所触发的事件类型; widget 引起事件的组件; width,heigh组件改变后的大小,仅Configure有效; x,y 鼠标当前位置,相对于窗口; x_root,y_root 鼠标当前位置,相对于整个屏幕 12、弹窗 messagebox._show函数的控制参数: default 指定消息框按钮; icon 指定消息框图标; message 指定消息框所显示的消息; parent 指定消息框的父组件; title 标题; type 类型; simpledialog模块参数: title 指定对话框的标题; prompt 显示的文字; initialvalue 指定输入框的初始值; filedialog 模块参数: filetype 指定文件类型; initialdir 指定默认目录; initialfile 指定默认文件; title 指定对话框标题 colorchooser模块参数: initialcolor 指定初始化颜色; title 指定对话框标题; 13、字体(font) 一般格式: (’Times -10 bold’) (‘Times’,10,’bold’,’italic’) 依次表示字体、字号、加粗、倾斜 补充: config 重新配置 label.config(font=’Arial -%d bold’ % scale.get()) 依次为字体,大小(大小可为字号大小),加粗 tkinter.StringVar 能自动刷新的字符串变量,可用set和get方法进行传值和取值,类似的还有IntVar,DoubleVar…
常用参数大总结
label:
def callback(): var.set("hhhhhhh") root = Tk() var = StringVar() var.set("66666") frame1 = Frame(root) frame2 = Frame(root) lb = Label(frame1,textvariable=var,padx=20) lb.pack(side=LEFT) # img = Image(file="1.gif",imgtype="photo") img = PhotoImage(file="1.gif") lb2 = Label(frame1,image=img) lb2.pack(side=RIGHT) btnCm = Button(frame2,text="下一步",command=callback) btnCm.pack() frame1.pack() frame2.pack() root.mainloop()
Checkbutton:
from tkinter import * root =Tk() v = IntVar() #选中为1,未选中为0 c = Checkbutton(root,text="Test",variable=v) c.pack() l = Label(root,textvariable=v) l.pack() root.mainloop()
from tkinter import * root =Tk() GIRLS = ["asd",'dsa','fef','fwaf'] v = [] def change(): for i in v: print(i.get()) for girl in GIRLS: v.append(IntVar()) b = Checkbutton(root,text=girl,variable=v[-1],command=change) #使用一个固有变量来记录状态 b.pack(anchor=W) #控件相对主窗口在左边 root.mainloop()
Radiobutton:
#对于单选框,多个按钮只对应一个变量,复选框,多个按钮对应多个值 from tkinter import * def change(): print(v.get()) root = Tk() v = IntVar() Radiobutton(root,text="one",variable=v,value=1,command=change).pack(anchor=W) Radiobutton(root,text="two",variable=v,value=2,command=change).pack(anchor=W) Radiobutton(root,text="three",variable=v,value=3,command=change).pack(anchor=W) root.mainloop()
from tkinter import * def change(): print(v.get()) root = Tk() v = IntVar() Langes = [ ("python",1), ("javascript",2), ("Lua",3), ("Ruby",4) ]
group = LabelFrame(root,text="选择喜欢的语言",padx=5,pady=5)
group.pack(padx=10,pady=10)
for key,val in Langes: Radiobutton(group,text=key,variable=v,value=val,command=change).pack(anchor=W) root.mainloop()
#对于单选框,多个按钮只对应一个变量,对于复选框,多个按钮对应多个值(使用列表获取)
注意: root = Tk() v = IntVar() 这里我们声明的变量全部应该写在主窗口生成后,才可以
不然当我们将变量写在主窗口生成前 v = IntVar() root = Tk() 会报错 AttributeError: 'NoneType' object has no attribute '_root'
1.首先进入IntVar类 class IntVar(Variable): def __init__(self, master=None, value=None, name=None): Variable.__init__(self, master, value, name) 2.进入父类 class Variable: def __init__(self, master=None, value=None, name=None): ... if not master: #看此处(master是主窗口,是传参,但是我们使用的时候并没有传入,所以为空,进入下面代码) master = _default_root #_default_root是什么 self._root = master._root() self._tk = master.tk ... 3._default_root查找 _support_default_root = 1 #也有用,后面看 _default_root = None #是一个全局变量,代表主窗口 但是他也为空,所以出现了上面的属性错误,None没有_root()方法 ------------------------------------------------------------------ 开始查看Tk() root = Tk() 1.查看源码 class Tk(Misc, Wm): def __init__(self, screenName=None, baseName=None, className='Tk', useTk=1, sync=0, use=None): ... if useTk: #这里默认传入1,进入下面逻辑 self._loadtk() ... 2.查看self._loadtk()方法 def _loadtk(self): self._tkloaded = 1 global _default_root # Version sanity checks ...... # Create and register the tkerror and exit commands # We need to inline parts of _register here, _ register # would register differently-named commands. ...... if _support_default_root and not _default_root: #查看上面的全局变量,发现可以进入下面的逻辑代码中 _default_root = self #所以_default_root就是主窗口 ...... ------------------------------------------------------------------ 结论:由上面发现可以知道: IntVar等变量的使用需要_default_root(当我们没有传入master时),而主窗口生成root=Tk()时,内部代码将_default_root实现了。所以两者顺序需要保证先后
Entry:
from tkinter import * root = Tk() input = Entry(root) input.pack(padx=20,pady=20) input.delete(0, END) #先清空按照索引 input.insert(0,"请输入内容...") root.mainloop()
from tkinter import * root = Tk() Lb1 = Label(root,text="作品:").grid(row=0,column=0) Lb1 = Label(root,text="作者:").grid(row=1,column=0) Ip1 = Entry(root) Ip1.grid(row=0,column=1,padx=10,pady=5) Ip2 = Entry(root) Ip2.grid(row=1,column=1,padx=10,pady=5) def show(): print("作品:《%s》"%Ip1.get()) print("作者:%s"%Ip2.get()) Button(root,text="获取数据",command=show).grid(row=3,column=0,sticky=W,padx=10,pady=5) Button(root,text="退出",command=root.quit).grid(row=3,column=1,sticky=E,padx=10,pady=5) root.mainloop()
from tkinter import * root = Tk() Lb1 = Label(root,text="账号:").grid(row=0,column=0) Lb1 = Label(root,text="密码:").grid(row=1,column=0) v1 = StringVar() v2 = StringVar() Ip1 = Entry(root) Ip1.grid(row=0,column=1,padx=10,pady=5) Ip2 = Entry(root,show="*") Ip2.grid(row=1,column=1,padx=10,pady=5) def show(): print("账号:%s"%Ip1.get()) print("密码:%s"%Ip2.get()) Button(root,text="获取数据",command=show).grid(row=3,column=0,sticky=W,padx=10,pady=5) Button(root,text="退出",command=root.quit).grid(row=3,column=1,sticky=E,padx=10,pady=5) root.mainloop()
from tkinter import * root = Tk() Lb1 = Label(root,text="账号:").grid(row=0,column=0) Lb1 = Label(root,text="密码:").grid(row=1,column=0) def test(): if Ip1.get() == "root": print("正确") return True else: print("错误") Ip1.delete(0,END) return False Ip1 = Entry(root,validate="focusout",validatecommand=test) Ip1.grid(row=0,column=1,padx=10,pady=5) Ip2 = Entry(root,show="*") Ip2.grid(row=1,column=1,padx=10,pady=5) root.mainloop()
#注意:只有当validatecommand验证失败,才会去触发invalidcommand事件.是为了避免函数过长,而且是代码简便 from tkinter import * root = Tk() Lb1 = Label(root,text="账号:").grid(row=0,column=0) Lb1 = Label(root,text="密码:").grid(row=1,column=0) def test(): if Ip1.get() == "root": print("正确") return True else: print("错误") Ip1.delete(0,END) return False def test2(): print("数据验证失败,我被调用...") Ip1 = Entry(root,validate="focusout",validatecommand=test,invalidcommand=test2) Ip1.grid(row=0,column=1,padx=10,pady=5) Ip2 = Entry(root,show="*") Ip2.grid(row=1,column=1,padx=10,pady=5) root.mainloop()
对于Entry中的get方法获取数据和textvariable参数中的StringVar类型数据的使用区别: --------------------------------------------------------------------- v1 = StringVar() Ip1 = Entry(root,textvariable=v1,validate="focusout",validatecommand=test,invalidcommand=test2) Ip1.get() v1.get() --------------------------------------------------------------------- 控件的get方法能够获取任何时候的输入框中的数据。 而textvariable中的值,当存在validate验证时,只有当验证通过后才会被赋值给变量textvariable。
补充:输入框的事件:
focus: 获得或失去时都调用
focusin: 获得焦点时调用
focusout: 失去焦点时
key: 当输入框被编辑时,(有按键输入)
none: 不会开启验证(默认),注意是字符none,不是None
补充:上面的验证函数都是没有参数的,随意添加参会报错
TypeError: test2() missing 1 required positional argument: '..'
那么如何传入参数?Tkinter为验证函数提供了一些参数
参数 | 含义 |
%d | 操作(触发事件)代码:0表示删除时触发,1插入时,2获得,失去焦点或textvariable值被修改 |
%i | 1.当用户尝试插入或删除操作的时候,该选项表示插入或删除的位置(索引号) 2.如果是由于获得,失去焦点或者textvariable值被修改,而调用验证函数,该值是-1 |
%P | 1.当输入框的值允许改变的时候,该值有效 2.该值为输入框的最新文本 |
%s | 该值为调用验证函数前输入框的文本内容 |
%S | 1.当插入或删除操作触发验证函数的时候,该值有效 2.该选项仅仅表示被插入或删除的值 |
%v | 该组件当前的validate选项的值(触发条件) |
%V | 1.调用验证函数的原因(触发条件) 2.focusin,focusout,key,forced(textvariable值被修改) |
%W | 该组件的名称(该控件的id) |
from tkinter import * root = Tk() Lb1 = Label(root,text="账号:").grid(row=0,column=0) Lb1 = Label(root,text="密码:").grid(row=1,column=0) def test(): if Ip1.get() == "root": print("正确") return True else: print("错误") Ip1.delete(0,END) return False def test2(p_con,s_con,v_func,v_res,w_name): print(p_con,s_con,v_func,v_res,w_name) #waff waff focusout focusout .44322320(和下面的id(Ip1)一致) return True v1 = StringVar() v2 = StringVar() #注意使用前需要先进行注册 testCMD = root.register(test2) Ip1 = Entry(root,textvariable=v1,validate="focusout",validatecommand=(testCMD,"%P","%s","%v","%V","%W")) print(id(Ip1)) #44322320 Ip1.grid(row=0,column=1,padx=10,pady=5) Ip2 = Entry(root,show="*") Ip2.grid(row=1,column=1,padx=10,pady=5) root.mainloop()
当然上面的只是提供的特殊参数,我们可以传入自己想要传递的数据,不过,这些自定义函数都是需要我们进行注册。
def test(a,b): print(a,b) if Ip1.get() == "root": print("正确") return True else: print("错误") Ip1.delete(0,END) return False testCMD2 = root.register(test) he = "hhhhh" ll = "gun" Ip1 = Entry(root,textvariable=v1,validate="focusout",validatecommand=(testCMD2,he,ll)) ------------------------------------------------------------------ hhhhh gun 正确
from tkinter import * root = Tk() v1 = StringVar() v2 = StringVar() v3 = StringVar() def test(content): if content.isdigit(): return True else: return False def calc(): res = int(v1.get())+int(v2.get()) v3.set(res) testCMD = root.register(test) e1 = Entry(root,textvariable=v1,validate="key",validatecommand=(testCMD,"%P")).grid(row=0,column=0) Lb1 = Label(root,text="+").grid(row=0,column=1) e2 = Entry(root,textvariable=v2,validate="key",validatecommand=(testCMD,"%P")).grid(row=0,column=2) Label = Label(root,text="=").grid(row=0,column=3) e3 = Entry(root,textvariable=v3,state="readonly").grid(row=0,column=4) Button(root,text="求和",command=calc).grid(row=2,column=2) root.mainloop()
补充:布局的pack和grid,和place区别
我们使用 pack 函数的时候,默认先使用的放到上面,然 后 依次向下排,它会给我们的组件一个自认为合适的位置 和大小,这是默认方式。
无严格界限要求。(简单布局推荐)
grid是严格按照表格的行列进行划分区域的,需要我们提前进行设计,灵活程度低于pack,但是对于我们理解更加容易(学习推荐)
place:允许用户指定组件的大小和位置(不推荐,但是在某些情况有妙用)
注意:pack和grid不要混用,不然无法进行
from tkinter import * master = Tk() photo = PhotoImage(file="1.gif") Lable(master,image=photo).pack() #会被button覆盖 def click(): print("center") Button(master,text="create",command=click).place(relx=0.5,rely=0.5,anchor=CENTER) #relx和rely是设置在窗口的位置在中间,anchor是设置这个控件相对于窗口中间的位置 master.mainloop()
from tkinter import * master = Tk() Label(master,bg="red").place(relx=0.5,rely=0.5,relheight=0.75,relwidth=0.75,anchor=CENTER) Label(master,bg="green").place(relx=0.5,rely=0.5,relheight=0.5,relwidth=0.5,anchor=CENTER) Label(master,bg="blue").place(relx=0.5,rely=0.5,relheight=0.25,relwidth=0.25,anchor=CENTER) master.mainloop()
继续说说pack中的参数:
side:按扭停靠在窗口的哪个位置
left: 左
top: 上
right: 右
botton: 下
fill:填充
x:水平方向填充
y:竖直方向填充
both:水平和竖直方向填充
none:不填充
expand:
yes:扩展整个空白区
no:不扩展
anchor:
N:北 下
E:东 右
S:南 下
W:西 左
CENTER:中间
padx:x方向的外边距
pady:y方向的外边距
ipadx:x方向的内边距
ipady:y方向的内边距
代码测试:
from tkinter import * root = Tk() Button(root,text='A').pack(side=LEFT,expand=NO,fill=Y) Button(root,text='B').pack(side=TOP,expand=NO,fill=BOTH) Button(root,text='C').pack(side=RIGHT,expand=NO,fill=NONE) Button(root,text='D').pack(side=LEFT,expand=NO,fill=Y) Button(root,text='E').pack(side=TOP,expand=NO,fill=BOTH) Button(root,text='F').pack(side=BOTTOM,expand=NO) Button(root,text='G').pack(anchor=SE) root.mainloop()
注意:expand,当你拉动窗口时(放大),所有你设置为允许扩充的控件都会去改变形状扩展空白区域(注意,我们设置的fill填充参数,当我们改变窗口大小时,也会随着设置的方向进行改变<前提是布局未被限制>)
Button(root,text='A').pack(side=LEFT,expand=YES,fill=Y)
expand:占据空白区域
fill:会填充设置的方向Y
至于grid就不再多说
Listbox:
from tkinter import * master = Tk() Lb = Listbox(master)#设置多选selectmode=EXTENDED Lb.pack() for item in ["福娃","f非","各方",'端口']: Lb.insert(END,item) #插入方向,从后方...(是按照索引来的) Btn = Button(master,text="删除当前选中",command=lambda x=Lb:x.delete(ACTIVE)) Btn.pack() master.mainloop()
from tkinter import * master = Tk() Lb = Listbox(master,selectmode=EXTENDED,) Lb.pack() for item in range(10): Lb.insert(END,item) #插入方向,从后方...(是按照索引来的) def del_lb(): ls = list(Lb.curselection()) ls.reverse() #需要先翻转过来,在从后向前删除(不然删除会导致索引不及时,删错元素) for index in ls: Lb.delete(index) Btn = Button(master,text="删除当前选中",command=del_lb) Btn.pack() master.mainloop()
from tkinter import * master = Tk() #1:生成滚动条 sb = Scrollbar(master) sb.pack(side=RIGHT,fill=Y) #2:生成ListBox,将其与滚动条相关联,yscrollcommand (单向关联:鼠标滚轮滚动内容,滚动条会滑动,但是滚动条变化时,内容不会变化) Lb = Listbox(master,selectmode=EXTENDED,height=11,yscrollcommand=sb.set) #默认显示10条,我们可以设置滚轮或者height行数 Lb.pack() #3:将滚动条滚动事件与ListBox的视图显示相关联 (单向关联 :滚动条变化时,内容会变化) sb.config(command=Lb.yview) #注意:2和3相关联会获得我们想要的结果 for item in range(15): Lb.insert(END,item) #插入方向,从后方...(是按照索引来的) master.mainloop()
Scale:
from tkinter import * master = Tk() s1 = Scale(master,from_ =0, to =42) #默认是垂直的 s1.pack() s2 = Scale(master,from_=0,to=200,orient=HORIZONTAL) #设置为水平 s2.pack() Button(master,text="获取数值",command=lambda :print(s1.get(),s2.get())).pack() master.mainloop()
from tkinter import * master = Tk() s1 = Scale(master,from_ =0, to =42,tickinterval=5) #tickinterval是设置分为几份 s1.pack() s2 = Scale(master,from_=0,to=200,orient=HORIZONTAL,resolution=10) #resolution设置每次移动的固定步长 s2.pack() Button(master,text="获取数值",command=lambda :print(s1.get(),s2.get())).pack() master.mainloop()
Text:功能多(方法多)
from tkinter import * master = Tk() text = Text(master,width=30,height=5) text.pack() # Special tags, marks and insert positions # SEL='sel' #选择的文字被替换 # SEL_FIRST='sel.first' #选中的文字的前面插入 # SEL_LAST='sel.last' #选中的文字后面被插入 # END='end' #在当前文档结尾插入 # INSERT='insert' #在当前光标位置插入 # CURRENT='current' #在当前位置插入 # ANCHOR='anchor' # ALL='all' # e.g. Canvas.delete(ALL) # def insert(self, index, chars, *args): # """Insert CHARS before the characters at INDEX. An additional # tag can be given in ARGS. Additional CHARS and tags can follow in ARGS.""" # self.tk.call((self._w, 'insert', index, chars) + args) text.insert(INSERT,"66666") text.insert(END,"888888") text.insert(CURRENT,"77777") text.insert(INSERT,"99999") master.mainloop()
from tkinter import * master = Tk() text = Text(master,width=200,height=200) text.pack() # Special tags, marks and insert positions # SEL='sel' #选择的文字被替换 # SEL_FIRST='sel.first' #选中的文字的前面插入 # SEL_LAST='sel.last' #选中的文字后面被插入 # END='end' #在当前文档结尾插入 # INSERT='insert' #在当前光标位置插入 # CURRENT='current' #在当前位置插入 # ANCHOR='anchor' # ALL='all' # e.g. Canvas.delete(ALL) # def insert(self, index, chars, *args): # """Insert CHARS before the characters at INDEX. An additional # tag can be given in ARGS. Additional CHARS and tags can follow in ARGS.""" # self.tk.call((self._w, 'insert', index, chars) + args) text.insert(INSERT,"66666") text.insert(END,"888888") photo = PhotoImage(file="1.gif") #注意photo对象写在函数体外,若在函数体中,生存周期一到,就会被释放。无法显示。,解释如下面所述 def show(): #此时是事件button点击,进入处理,处理后,才会进入IO循环中去显示数据,若是数据在函数体中被回收,那么久无法显示出来 a = "adsafafw" #字符串是被存放在常量区,不会被删除的,所以两个的id是一致的 text.image_create(INSERT,image=photo) text.insert(END,a) print(id(a)) #17019440 def test(): b = "adsafafw" print(id(b)) # 17019440 和上面的数据a都是在函数体中,id一致。是使用的一个数据(存放在常量区) test() btn = Button(text,text="试试看",command=show) text.window_create(INSERT,window=btn) #要想显示控件,需要将text设置为窗口("""Create a window at INDEX.""") master.mainloop()
from tkinter import * master = Tk() text = Text(master,width=100,height=20) text.pack() text.insert(CURRENT,"adfwgthjdjxc") #注意行数是从1开始,列数是从0开始,索引写法可以使用小数点连接:1.2---第一行第3列 特殊:行.end(该行最后的索引),特殊的需要使用引号 txt = text.get(1.2,'1.end') #"""Return the text from INDEX1 to INDEX2 (not included).""" txt2 = text.get(1.1,1.6) print(txt,txt2) #fwgthjdjxc dfwgt master.mainloop()
from tkinter import * master = Tk() text = Text(master,width=100,height=20) text.pack() text.insert(CURRENT,"fgweagawgrhssdf") #Marks标记 #1.简单使用: text.mark_set("bj","1.3") #在1.3处设置标记,名为bj,就像书签一样,方便操作。注意mark_set和mark_unset对应 #默认标记是记住右边的那个字符(第一次设置后就跟定他了)e字符 text.insert("bj","66") #fgw66eagawgrhssdf 向e字符左端插入 text.insert("bj",'88') #fgw6688eagawgrhssdf 还是向e字符左端插入 text.mark_unset("bj") text.delete(1.0,END) #清空数据 #2.标志被删除了之后的反应: text.insert(CURRENT,"fgweagawgrhssdf") text.mark_set("bj","1.3") #在1.3处设置标记,名为bj,就像书签一样,方便操作。注意mark_set和mark_unset对应 text.delete(1.2,1.5) #注意当标记位置被删除了的话,会自动寻找到删除的字符串的下一个字符,以他为标志 #删除字符串后面的那个紧接的字符是g,以他为标志 text.insert("bj","66") #fg66gawgrhssdf 向g字符左端插入 text.insert("bj",'88') #fg6688gawgrhssdf 还是向g字符左端插入 text.mark_unset("bj") text.delete(1.0,END) #3.前面都是以标志位为基准,放在右边。修改将标志位放在左边:mark_gravity text.insert(CURRENT,"fgweagawgrhssdf") text.mark_set("bj","1.3") #在1.3处设置标记,名为bj,就像书签一样,方便操作。注意mark_set和mark_unset对应 text.mark_gravity("bj",LEFT) #默认标记是记住右边的那个字符(第一次设置后就跟定他了)e字符 text.insert("bj","66") #fgw66eagawgrhssdf 向e字符左端插入 text.insert("bj",'88') #fgw6688eagawgrhssdf 还是向e字符左端插入 text.mark_unset("bj") master.mainloop()
from tkinter import * master = Tk() text = Text(master,width=100,height=20) text.pack() text.insert(CURRENT,"gag g efwa h eshhe fawf") text.tag_add("tag1","1.7","1.12","1.16") #索引双数为范围,单数为一个字符 text.tag_config("tag1",background="yellow",foreground="white") #config是设置样式 foreground是前景色,字体颜色 #新样式覆盖旧样式 text.tag_add("tag2","1.9","1.12") #索引双数为范围,单数为一个字符 text.tag_config("tag2",background="blue",foreground="white") #config是设置样式 foreground是前景色,字体颜色 #设置tag的优先级:作用就是较低的优先级样式是无法覆盖高优先级的 text.tag_lower("tag2") #降低 # text.tag_raise("tag1") #提高 master.mainloop()
from tkinter import * import webbrowser master = Tk() text = Text(master,width=100,height=20,selectbackground="green") text.pack() text.insert(CURRENT,"gag g efwa h eshhe fawf") text.tag_add("a","1.7","1.12","1.16") #索引双数为范围,单数为一个字符 text.tag_config("a",background="yellow",foreground="red",underline=True,font="12") #config是设置样式 foreground是前景色,字体颜色 def show_arrow_cursor(*args): text.config(cursor="arrow") #箭头 def show_xterm_cursor(*args): text.config(cursor="xterm") #光标线 def click(*args): webbrowser.open("http://www.baidu.com") text.tag_bind("a","",show_arrow_cursor) # 是鼠标进入的样式 text.tag_bind("a"," ",show_xterm_cursor) #鼠标离开 text.tag_bind("a"," ",click) #单击样式 # def tag_bind(self, tagName, sequence, func, add=None): master.mainloop() SEQUENCE is a string of concatenated event patterns. An event pattern is of the form where MODIFIER is one of Control, Mod2, M2, Shift, Mod3, M3, Lock, Mod4, M4, Button1, B1, Mod5, M5 Button2, B2, Meta, M, Button3, B3, Alt, Button4, B4, Double, Button5, B5 Triple, Mod1, M1. TYPE is one of Activate, Enter, Map, ButtonPress, Button, Expose, Motion, ButtonRelease FocusIn, MouseWheel, Circulate, FocusOut, Property, Colormap, Gravity Reparent, Configure, KeyPress, Key, Unmap, Deactivate, KeyRelease Visibility, Destroy, Leave and DETAIL is the button number for ButtonPress, ButtonRelease and DETAIL is the Keysym for KeyPress and KeyRelease. Examples are 1> for pressing Control and mouse button 1 or for pressing A and the Alt key (KeyPress can be omitted). An event pattern can also be a virtual event of the form < > where AString can be arbitrary. This event can be generated by event_generate. If events are concatenated they must appear shortly after each other. FUNC will be called if the event sequence occurs with an instance of Event as argument. If the return value of FUNC is "break" no further bound function is invoked. An additional boolean parameter ADD specifies whether FUNC will be called additionally to the other bound function or whether it will replace the previous function. Bind will return an identifier to allow deletion of the bound function with unbind without memory leak. If FUNC or SEQUENCE is omitted the bound function or list of bound events are returned."""
from tkinter import * import hashlib master = Tk() text = Text(master,width=100,height=20,selectbackground="green") text.pack() text.insert(INSERT,"gag g efwa h eshhe fawf") contents = text.get(1.0,END) def getData(contents): data = hashlib.md5(contents.encode()) return data.hexdigest() cont = getData(contents) def check(): data = getData(text.get(1.0,END)) if data != cont: print("内容不一致") else: print("检测通过") Button(master,text="检测",command=check).pack() master.mainloop()
补充:使用hashlib进行文本(文件)比较
1.对于本地文件的比较:倾向于直接读取文件进行比较,毕竟hash计算也是需要读取文件内容,然后进行计算,对于两个文件,都要读取完毕,然后进行md5再进行比较。可能消耗会大于直接读取文件进行比较
2.对于网络传输文件,我们为了节省流量,最后在本地进行hash,向md5最后只需要在网络上传输32位数据即可。
推文:https://www.v2ex.com/t/257552
from tkinter import * import hashlib root = Tk() text = Text(root,width=30,height=5) text.pack() text.insert(INSERT,"fea g ag awgwag\r\n") text.insert(INSERT,"ffge g agge awgag") def getIndex(text,index): #因为这个索引是一个小数 n.m n行m列,所以我们需要进一步处理 print(text,index) return tuple(map(int,str.split(text.index(index),'.'))) #map(func,iter) 这里func-->int() iter--->[n,m]可迭代 start = '1.0' while True: pos = text.search('g',start,stopindex=END) if not pos: break print("找到位置是:",getIndex(text,pos)) start = pos + "+1c" mainloop()
from tkinter import * import hashlib master = Tk() text = Text(master,width=100,height=20,undo=True) text.pack() text.insert(INSERT,"gag g efwa h eshhe fawf") def undo(): text.edit_undo() Button(master,text="撤销",command=undo).pack() master.mainloop()
默认会在每一次完整的操作后面加上一个“分隔符”入栈。那么什么是一次完整的操作:
是指每次焦点切换(鼠标移动点击改变光标位置,后进行操作),用户按下Enter,删除\插入操作的转换等之前的操作算是一次完整的操作(对于连续相同的操作,也只能算作一次完整的操作)
from tkinter import * import hashlib master = Tk() text = Text(master,width=100,height=20,undo=True,autoseparators=False) text.pack() text.insert(INSERT,"gag g efwa h eshhe fawf") def cusSep(*args): #每次调用该函数,就还在该位置插入一个分隔符 text.edit_separator() text.bind('',cusSep) def undo(): text.edit_undo() Button(master,text="撤销",command=undo).pack() master.mainloop()
Canvas:(绘图使用)
from tkinter import * master = Tk() w = Canvas(master,width=200,height=100) #创建绘图区域,默认在主窗口居中 w.pack() line1 = w.create_line(0,50,200,50,fill="yellow") line2 = w.create_line(100,0,100,100,fill="red",dash=(12,4)) #dash中元组第一个代表点划线长,第二个代表间隔长度 rect1 = w.create_rectangle(50,25,150,75,fill="blue") w.coords(line1,0,25,200,25) #坐标移动,至少4个参数,基本上就是重新绘制这条线 w.delete(line2) #删除这条线 w.itemconfig(rect1,fill="red") #对某一个创建的图形项目进行配置属性 w.itemconfig(line1,fill="green") Button(master,text="删除所有",command=lambda x=ALL:w.delete(x)).pack() master.mainloop()
from tkinter import * master = Tk() w = Canvas(master,width=200,height=100) w.pack() w.create_line(0,0,200,100,fill="green",width=3) #width是线宽 w.create_line(200,0,0,100,fill="green",width=3) w.create_rectangle(40,20,160,80,fill="green") w.create_rectangle(65,35,135,65,fill="yellow") #填充文字 w.create_text(100,50,text="fwfwaf") master.mainloop()
from tkinter import * master = Tk() w = Canvas(master,width=200,height=100) w.pack() w.create_rectangle(40,20,160,80,fill="green",dash=(4,4)) w.create_oval(40,20,160,80,fill="pink") #创建椭圆 w.create_arc(40,20,160,80,fill="blue",width=3) #创建扇形需两个点,作为两个端点 w.create_polygon(40,20,160,80,30,10,40,20,fill="white") #绘制多边形,会自动封闭图形(首尾) master.mainloop()
from tkinter import * import math master = Tk() w = Canvas(master,width=200,height=100) w.pack() center_x = 100 center_y = 50 r = 50 points = [ #左上点 center_x - int(r*math.sin(2*math.pi/5)), center_y - int(r*math.cos(2*math.pi/5)), #右上点 center_x + int(r*math.sin(2*math.pi/5)), center_y - int(r*math.cos(2*math.pi/5)), #左下角 center_x - int(r*math.sin(math.pi/5)), center_y + int(r*math.cos(math.pi/5)), #顶点 center_x, center_y - r, #右下角 center_x + int(r*math.sin(math.pi/5)), center_y + int(r*math.cos(math.pi/5)), ] print(points) w.create_polygon(points,fill="green",outline="black") #轮廓线 master.mainloop()
from tkinter import * master = Tk() w = Canvas(master,width=200,height=100) w.pack() def paint(event): #事件触发 x1, y1 = (event.x-1,event.y-1) x2, y2 = (event.x+1,event.y+1) w.create_oval(x1,y1,x2,y2) w.bind("",paint) #鼠标左键点击移动 master.mainloop()
from tkinter import * root = Tk() # 创建一个Canvas,设置其背景色为白色 cv = Canvas(root,bg = 'white') d = {1:'error',2:'info',3:'question',4:'hourglass'} for i in d: cv.create_bitmap((20*i,20*i),bitmap = d[i]) cv.pack() root.mainloop() # 使用bitmap属性来指定位图的名称,这个函数的第一个参数为一个点(x,y)指定位图存放位置的左上位置。
from tkinter import * master = Tk() w = Canvas(master,width=200,height=100) w.pack() img = PhotoImage(file="1.gif") w.create_image((0,0),image=img) master.mainloop()
from tkinter import * master = Tk() w = Canvas(master,width=200,height=100) w.pack() def printCanvas(): print("window") btn = Button(w,text="点我呀!",command=printCanvas) w.create_window((10,10),window=btn,anchor=W) w.create_line(10,10,100,100) #默认组件的优先级高,会覆盖重叠部分 master.mainloop()
推文:
Tkinter教程之Canvas篇(4)
menu:菜单使用
from tkinter import * master = Tk() def clb(): print("dawfwa") menubar = Menu(master) #顶级菜单的创建 menubar.add_command(label="hello",command=clb) menubar.add_command(label="quit",command=master.quit) master.config(menu=menubar) master.mainloop()
from tkinter import * master = Tk() def callback(): print("dawfwa") menubar = Menu(master) #子菜单 filemenu = Menu(menubar,tearoff=False) #设置不可分离,不会在菜单界面显示一条虚线(可分离菜单窗口) filemenu.add_command(label="打开",command=callback) filemenu.add_command(label="保存",command=callback) filemenu.add_separator() filemenu.add_command(label="退出",command=master.quit) editmenu = Menu(menubar) editmenu.add_command(label="剪切",command=callback) editmenu.add_command(label="拷贝",command=callback) editmenu.add_command(label="复制",command=callback) #级联菜单 #顶级菜单 menubar.add_cascade(label="文件",menu=filemenu) menubar.add_cascade(label="编辑",menu=editmenu) #配置后才能显示 master.config(menu=menubar) master.mainloop()
from tkinter import * master = Tk() def callback(): print("dawfwa") menubar = Menu(master) menubar.add_command(label="查询",command=callback) menubar.add_command(label="重做",command=master.quit) frame = Frame(master,width=512,height=512) frame.pack() def popup(event): menubar.post(event.x,event.y) #post是相对于整个屏幕,而不是程序窗口,而event.x/y是获取的相对于程序窗口的尺寸,所以我们需要使用event.x_root/y_root去获取屏幕尺寸 #frame是一个框架区域,其中可以包含其他控件,是一个独立的区域划分,我们在这个区域中绑定事件 frame.bind("",popup) #-1是左键,-2是中间滑轮点击,-3是右键 master.config(menu=menubar) master.mainloop()
from tkinter import * master = Tk() def callback(): print("dawfwa") menubar = Menu(master) openvar = IntVar() savevar = IntVar() quitvar = IntVar() #子菜单 filemenu = Menu(menubar,tearoff=False) #设置不可分离,不会在菜单界面显示一条虚线(可分离菜单窗口) filemenu.add_checkbutton(label="打开",command=callback,variable=openvar) filemenu.add_checkbutton(label="保存",command=callback,variable=savevar) filemenu.add_separator() filemenu.add_checkbutton(label="退出",command=master.quit,variable=quitvar) editvar = IntVar() editmenu = Menu(menubar) editmenu.add_radiobutton(label="剪切",command=callback,variable=editvar) editmenu.add_radiobutton(label="拷贝",command=callback,variable=editvar) editmenu.add_radiobutton(label="复制",command=callback,variable=editvar) #级联菜单 #顶级菜单 menubar.add_cascade(label="文件",menu=filemenu) menubar.add_cascade(label="编辑",menu=editmenu) master.config(menu=menubar) master.mainloop()
from tkinter import * master = Tk() def callback(): print("dawfwa") mb = Menubutton(master,text=">",relief=RAISED) mb.pack() filenemu = Menu(mb,tearoff=False) #顶级菜单 filenemu.add_command(label="文件",command=callback) filenemu.add_command(label="编辑",command=callback) mb.config(menu=filenemu) master.mainloop()
OptionMenu:实现下拉列表框(就是HTML中select)
from tkinter import * OPTION = [ "fawf", "4545", "fafwa2", ] master = Tk() v = StringVar() v.set("one") #def __init__(self, master, variable, value, *values, **kwargs): # w = OptionMenu(master,v,OPTION) #不加星号,进行解包,那么只能看做value被输出 #加星号,列表被序列解包,正常输出*values w = OptionMenu(master,v,*OPTION) w.pack() master.mainloop()
事件处理(事件绑定bind)
事件序列是包含在<>中 type部分是最重要的,他通常用于描述普通的事件类型 modifier是可选的,用于描述组合键Ctrl+C,Ctrl+Shift... detail也是可选的,他通常用于描述具体的按键, 1> 1代表左键 2 中间滚轮 3 右键
class Misc: """Internal class. Base class which defines methods common for interior widgets.""" def bind(self, sequence=None, func=None, add=None): """Bind to this widget at event SEQUENCE a call to function FUNC. SEQUENCE is a string of concatenated event patterns. An event pattern is of the formwhere MODIFIER is one of Control, Mod2, M2, Shift, Mod3, M3, Lock, Mod4, M4, Button1, B1, Mod5, M5 Button2, B2, Meta, M, Button3, B3, Alt, Button4, B4, Double, Button5, B5 Triple, Mod1, M1. TYPE is one of Activate, Enter, Map, ButtonPress, Button, Expose, Motion, ButtonRelease FocusIn, MouseWheel, Circulate, FocusOut, Property, Colormap, Gravity Reparent, Configure, KeyPress, Key, Unmap, Deactivate, KeyRelease Visibility, Destroy, Leave and DETAIL is the button number for ButtonPress, ButtonRelease and DETAIL is the Keysym for KeyPress and KeyRelease. Examples are #可以进行事件组合 :用户同时按下Ctrl+Shift+H才会触发 1> for pressing Control and mouse button 1 or for pressing A and the Alt key (KeyPress can be omitted). An event pattern can also be a virtual event of the form < > where AString can be arbitrary. This event can be generated by event_generate. If events are concatenated they must appear shortly after each other. FUNC will be called if the event sequence occurs with an instance of Event as argument. If the return value of FUNC is "break" no further bound function is invoked. An additional boolean parameter ADD specifies whether FUNC will be called additionally to the other bound function or whether it will replace the previous function. Bind will return an identifier to allow deletion of the bound function with unbind without memory leak. If FUNC or SEQUENCE is omitted the bound function or list of bound events are returned.""" return self._bind(('bind', self._w), sequence, func, add)
class Event: """Container for the properties of an event. Instances of this type are generated if one of the following events occurs: KeyPress, KeyRelease - for keyboard events ButtonPress, ButtonRelease, Motion, Enter, Leave, MouseWheel - for mouse events Visibility, Unmap, Map, Expose, FocusIn, FocusOut, Circulate, Colormap, Gravity, Reparent, Property, Destroy, Activate, Deactivate - for window events. If a callback function for one of these events is registered using bind, bind_all, bind_class, or tag_bind, the callback is called with an Event as first argument. It will have the following attributes (in braces are the event types for which the attribute is valid): serial - serial number of event num - mouse button pressed (ButtonPress, ButtonRelease) focus - whether the window has the focus (Enter, Leave) height - height of the exposed window (Configure, Expose) width - width of the exposed window (Configure, Expose) keycode - keycode of the pressed key (KeyPress, KeyRelease) state - state of the event as a number (ButtonPress, ButtonRelease, Enter, KeyPress, KeyRelease, Leave, Motion) state - state as a string (Visibility) time - when the event occurred x - x-position of the mouse y - y-position of the mouse x_root - x-position of the mouse on the screen (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion) y_root - y-position of the mouse on the screen (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion) char - pressed character (KeyPress, KeyRelease) send_event - see X/Windows documentation keysym - keysym of the event as a string (KeyPress, KeyRelease) keysym_num - keysym of the event as a number (KeyPress, KeyRelease) type - type of the event as a number widget - widget in which the event occurred delta - delta of wheel movement (MouseWheel) """ pass
from tkinter import * master = Tk() def callback(event): print("点击位置:",event.x,event.y) frame = Frame(master,width=200,height=200) frame.pack() #绑定事件 frame.bind("",callback) #鼠标左键 frame.bind(" ",callback) #鼠标滚轮 frame.bind(" ",callback) #鼠标右键 master.mainloop()
from tkinter import * master = Tk() def callback(event): # print("获取的键盘值:",event.keysym) #可以获取所有的键盘值,但是对于输入法输入的中文等不能识别,为?? # print("获取的输入值:",event.char) #获取用户输入,对于特殊,像shift等是不能捕获,为空 char = event.char if not char: char = event.keysym print("获取的值:",char) frame = Frame(master,width=200,height=200) frame.pack() #绑定事件 frame.bind("",callback) #键盘按键Key, KeyPress, KeyRelease frame.focus_set() master.mainloop()
....其他看上面红色部分
其他组件:
from tkinter import * master = Tk() m = Message(master,text="fafw\ndwafawfawfawfwafawffwafaw",width=100) m.pack() master.mainloop()
from tkinter import * master = Tk() # sx = Spinbox(master,from_=0,to=10) #0-10 # sx.pack() sx = Spinbox(master,values=("dasf","fafw","gea")) sx.pack() master.mainloop()
#coding:utf-8 from tkinter import * master = Tk() #PanedWindow和Frame相似,都是未组件提供一个框架,不过PanedWindow允许用户调整应用程序得空间划分 pw = PanedWindow(orient=VERTICAL) pw.pack() top = Label(pw,text="top paned") pw.add(top) bottom = Label(pw,text="Bottom paned") pw.add(bottom) master.mainloop()
#coding:utf-8 from tkinter import * master = Tk() #PanedWindow和Frame相似,都是未组件提供一个框架,不过PanedWindow允许用户调整应用程序得空间划分 pw1 = PanedWindow(showhandle=True,sashrelief=SUNKEN) #默认水平 showhandle显示手柄,sashrelief显示边框 pw1.pack(fill=BOTH,expand=1) left = Label(pw1,text="left paned") pw1.add(left) pw2 = PanedWindow(orient=VERTICAL,showhandle=True,sashrelief=SUNKEN) pw1.add(pw2) top = Label(pw2,text="top paned") bottom = Label(pw2,text="bottom paned") pw2.add(top) pw2.add(bottom) master.mainloop()
#coding:utf-8 from tkinter import * master = Tk() #Toplevel创建顶级窗口 def create(): top = Toplevel() top.attributes("-alpha",0.5) #加-的原因是:最后是以命令行去调用Windows sdk alpha是透明度 top.title("hello") msg = Message(top,text="gegaegagagag\nagfawfa") msg.pack() Button(master,text="create",command=create).pack() master.mainloop()
三种标准对话框模块
- messagebox
- filedialog
- colorchooser
在低版本中这三个对话框放在不同的模块tkMessageBox,tkFileDialog,tkColorChooser
from tkinter import * from tkinter import messagebox master = Tk() ret = messagebox.askokcancel("title","question") #askyesno #askretrycancel #上面返回布尔型 #showerror #showinfo #showwarning #返回OK表示按下了是 #askquestion #返回yes或者no表示点击是或否 print(ret) master.mainloop()
filedialog模块提供两个函数askopenfilename和asksaveasfilename()
分别用于打开文件和保存文件
from tkinter import * from tkinter import filedialog master = Tk() def callback(): filename = filedialog.askopenfilename(filetypes=[("PNG",".png"),("GIF",".gif"),("JPG",".jpg")]) print(filename) Button(master,text="open file",command=callback).pack() master.mainloop()
from tkinter import * from tkinter import filedialog master = Tk() def callback(): filename = filedialog.askopenfilename(defaultextension=".png") print(filename) #defaultextension设置默认后缀,不能对文件起到过滤,只是当你选择文件未写后缀的话为你加上defaultextension,再进行筛选 Button(master,text="open file",command=callback).pack() master.mainloop()
initialdir:设置默认打开文件夹目录
title:设置标题
parent:设置父窗口,默认根窗口
from tkinter import * from tkinter import colorchooser master = Tk() def callback(): color= colorchooser.askcolor() print(color) #((109.42578125, 115.44921875, 211.82421875), '#6d73d3') rgb和16进制值 Button(master,text="choose color",command=callback).pack() master.mainloop()
暂时完成。 还有其他工具包PyQT和PyGTK也是使用十分广泛的。