GUI介绍
- GreaphicalUserInterface
- GUI for Python:Tkinter,wxPython,PyQt
- Tkinter
- 绑定的是TK GUI工具集,用途Python包装的TCL代码
- PyGTK
- Tkinter的替代品
- wxPython
- 跨平台的Python GUI
- PyQt
- 跨平台的
- 商业授权可能有问题
- 推荐资料
- 辛星GUI,辛星Python
- Python GUI Programming cookbook
- Tkinter reference a GUI for Python
- 案例v1.py
# 测试Tkinter包是否好用 import tkinter tkinter._test()- 案例v2.py
# hello world import tkinter base = tkinter.Tk() # 消息循环 base.mainloop()
Tkinter 常用组件
- 按钮
- Button 按钮组件
- RadioButton 单选框组件
- checkButton 复选框组件
- Listbox 列表框组件
- 文本输入组件
- Entry 单行文本框组件
- text 多行文本框组件
- 标签组件
- Label 标签组件,可以显示图片和文字
- Message 标签组件,可以根据内容将文字转换
- 菜单
- Menu 菜单组件
- MenuButton 菜单按钮组件,可以使用Menu代替
- 滚动条
- scale 滑块组件
- Scrollbar 滚动条组件
- 其他组件
- Canvas 画布组件
- Frame 框架组件,将多个组件编组
- Toplevel 创建子窗口器组件
- 案例v3.py
# Label的例子 import tkinter base = tkinter.Tk() # 负责标题 base.wm_title("Label Test") lb = tkinter.Label(base, text = "Python Label") # 给相应组件指定布局 lb.pack() base.mainloop()
组件的大致使用步骤
- 创建总面板
- 创建面板上的各种组件
- 指定组件的父组件,即依附关系
- 利用相应的属性对组件进行设置
- 给组件安排布局
- 同步骤2相似,创建好过个组件
- 最后,启动总面板的消息循环
- 案例v4.py
# 设置Label的例子 import tkinter base = tkinter.Tk() base.wm_title("Label Test") # 支持属性很多background,font,underline等 # 第一个参数,指定属性 lb1 = tkinter.Label(base, text = "Python AI") lb1.pack() lb2 = tkinter.Label(base, text = "绿色背景", background = "green") lb2.pack() lb3 = tkinter.Label(base, text = "蓝色背景", background = "blue") lb3.pack() base.mainloop() - 案例v5.py
# Button的案例 import tkinter def showLabel(): global baseFrame # 在函数中定义了一个label # label的父组件是baseFrame lb = tkinter.Label(baseFrame, text = "显示Label") lb.pack() baseFrame = tkinter.Tk() # 生成一个按钮 # command参数指示,当按钮按下的时候,执行哪个函数 btn = tkinter.Button(baseFrame, text = "Show Label", command = showLabel) # btn = tkinter.Button(baseFrame, text = "Show Label") btn.pack() baseFrame.mainloop() ''' Button的属性: anchor 设置按钮中文字的对其方式,相对于按钮的中心位置 background(bg) 设置按钮的背景颜色 foreground(fg) 设置按钮的前景色(文字的颜色) borderwidth(bd) 设置按钮边框宽度 cursor 设置鼠标在按钮上的样式 command 设定按钮点击时触发的函数 bitmap 设置按钮上显示的位图 font 设置按钮上文本的字体 width 设置按钮的宽度 (字符个数) height 设置按钮的高度 (字符个数) state 设置按钮的状态 text 设置按钮上的文字 image 设置按钮上的图片 '''
组件布局
控制组件的摆放方式
三种布局
- pack:按照方位布局
- place:按照坐标布局
- grid:网格布局
pack布局
- 最简单,代码量少,挨个摆放,默认从上到下,系统自动设置
- 通过使用方式为:组件对象.pack(设置,,,,)
- side:停靠方位, 可选值为LEFT,TOP,RIGHT,BOTTON
- fill:填充方式,X,Y,BOTH,NONE
- expand:YES/NO
- anchor: N,E,S,W,CENTER
- ipadx:x方向的内边距
- ipady:y
- padx:x方向的内边距
- pady:y
- 案例v6.py
# pack布局案例 import tkinter baseFrame = tkinter.Tk() # 以下所有代码都是创建一个组件,然后看布局 btn1 = tkinter.Button(baseFrame, text = "A") btn1.pack(side=tkinter.LEFT, expand=tkinter.YES, fill = tkinter.Y) btn2 = tkinter.Button(baseFrame, text = "B") btn2.pack(side=tkinter.TOP, expand=tkinter.YES, fill = tkinter.BOTH) btn3 = tkinter.Button(baseFrame, text = "C") btn3.pack(side=tkinter.RIGHT, expand=tkinter.YES, fill = tkinter.NONE, anchor=tkinter.NE) btn4 = tkinter.Button(baseFrame, text = "D") btn4.pack(side=tkinter.LEFT, expand=tkinter.NO, fill = tkinter.Y) btn5 = tkinter.Button(baseFrame, text = "E") btn5.pack(side=tkinter.TOP, expand=tkinter.NO, fill = tkinter.BOTH) btn6 = tkinter.Button(baseFrame, text = "F") btn6.pack(side=tkinter.BOTTOM, expand=tkinter.YES) btn7 = tkinter.Button(baseFrame, text = "G") btn7.pack(anchor=tkinter.SE) baseFrame.mainloop()
grid布局
- 通用使用方式:组件对象.grid(设置,,,)
- 利用row,column编号,都是从0开始
- sticky:N,E,S,W表示上下左右,用来决定组件从哪个方向开始
- 支持ipadx,padx等参数,跟pack函数含义一样
- 支持rowspan,columnspan,表示跨行,跨列数量
- 案例v7.py
# grid布局案例 import tkinter baseFrame = tkinter.Tk() # 下面被注释掉的一行代码跟下面两行代码等效 #lb1 = tkinkter.Label(baseFrame, text="账号:").grid(row=0, sticky=tkinter.W) lb1 = tkinter.Label(baseFrame, text = "账号:") lb1.grid(row=0, sticky=tkinter.W) en1 = tkinter.Entry(baseFrame) en1.grid(row=0, column=1, sticky=tkinter.E) lb2 = tkinter.Label(baseFrame, text = "密码:").grid(row=1, sticky=tkinter.W) en2 = tkinter.Entry(baseFrame).grid(row=1, column=1, sticky=tkinter.E) btn = tkinter.Button(baseFrame, text = "登录").grid(row=2, column=1, sticky=tkinter.W) baseFrame.mainloop()
place布局
- 明确方位的摆放
- 相对位置布局,随意改变窗口大小会导致混乱
- 使用place函数,分为绝对布局和相对布局,绝对布局使用x,y参数
- 相对布局使用relx,rely,relheight,relwidth
消息机制
- 消息的传递机制
- 自动发出事件/消息
- 消息有系统负责发送到队列
- 由相关组件进行绑定/设置
- 后端自动选择感兴趣的事件并作出相应的反应
- 消息格式
- <[modifier-]---type-[-detail]>
- :Button表示一个按钮事件,1代表的是鼠标左键,2代表中键
- :键盘A键位
- :同时按下Control,Shift,A三个键位
- :F键盘
- 键位对应的名称
- 案例v8.py
# 事件简单的例子 import tkinter def baseLabel(event): global baseFrame print("哈哈,我被点击了") lb = tkinter.Label(baseFrame, text = "谢谢点击") lb.pack() # 画出程序的总框架 baseFrame = tkinter.Tk() lb = tkinter.Label(baseFrame, text = "模拟按钮") # label绑定相应的消息和处理函数 # 自动获取左键点击,并启动相应的处理函数baseLabel lb.bind("<Button-1>", baseLabel) lb.pack() # 启动消息循环 # 到此,表示程序开始运行 baseFrame.mainloop()
Tkinter的绑定
- bind_all:全局范围的绑定,默认的是全局快捷键,比如F1是帮助文档
- bind_class:接受三个参数,第一个是类名,第二个是事件,第三个是操作
- w.bind_class("Entry", "", my_paste)
- bind:单独对某一个实例绑定
- unbind:解绑,需要一个参数,即你要解绑哪个事件
- 输入框,功能单一
- entry["show"]="*",设置遮挡字符
- 案例v9.py
# 输入框案例 import tkinter # 模拟的是登录函数 def reg(): # 从相应的输入框中,得到用户的输入 name = e1.get() pwd = e2.get() t1 = len(name) t2 = len(pwd) if name == "111" and pwd == "222": # 需要理解下面代码的含义 lb3["text"] = "登录成功" else: lb3["text"] = "用户名或密码错误" # 输入框删除掉用户输入的内容 # 注意delete的两个参数,表示从第几个删除到第几个 e1.delete(0, t1) e2.delete(0, t2) # 启动舞台 baseFrame = tkinter.Tk() lb1 = tkinter.Label(baseFrame, text = "用户名:") lb1.grid(row = 0, column = 0, stick = tkinter.W) e1 = tkinter.Entry(baseFrame) e1.grid(row = 0, column = 1, stick = tkinter.E) lb2 = tkinter.Label(baseFrame, text = "密码:") lb2.grid(row = 1, column = 0, stick = tkinter.W) e2 = tkinter.Entry(baseFrame) e2.grid(row = 1, column = 1, stick = tkinter.E) #e2['show'] = '*' # Button参数command的意思是,当按钮被点击后启动相应的处理函数 btn = tkinter.Button(baseFrame, text = "登录", command = reg) btn.grid(row = 2, column = 1, stick = tkinter.E) lb3 = tkinter.Label(baseFrame, text = "") lb3.grid(row = 3) # 启动主Frame baseFrame.mainloop()
菜单
- 第一个Menu类定义的是parent
- add_command添加菜单选项,如果菜单是顶层菜单,则从左向右添加,否则就是下拉菜单
- label:指定菜单项名称
- command:点击后相应的调用函数
- acceletor:快捷键
- underline:指定是否菜单信息下有下划线
- menu:属性定制使用哪一个作为顶级菜单
- 案例v10.py
# 普通菜单代码 import tkinter baseFrame = tkinter.Tk() menubar = tkinter.Menu(baseFrame) for item in ['File', 'Edit', 'View', 'About']: menubar.add_command(label=item) baseFrame['menu'] = menubar baseFrame.mainloop()
- add_cascade:级联菜单,作用是引出后面的菜单
- add_cascade的menu属性:指明把菜单级联到哪个菜单上
- label:名称
- 建立menu实例
- add_command
- add_cascade
- 案例v11.py
import tkinter baseFrame = tkinter.Tk() menubar = tkinter.Menu(baseFrame) emenu = tkinter.Menu(menubar) for item in ['Copy', 'Past', 'Cut']: emenu.add_command(label = item) menubar.add_cascade(label='File') menubar.add_cascade(label='Edit', menu = emenu) menubar.add_cascade(label='About') baseFrame['menu'] = menubar baseFrame.mainloop()
- 弹出菜单也叫上下文菜单
- 实现的大致思路
- 简单菜单并向菜单添加各种功能
- 监听鼠标右键
- 如果右键点击,则根据位置判断弹出
- 调用Menu的pop方法
- add_separator:添加分隔符
- 案例v12.py
import tkinter def makeLabel(): global baseFrame tkinter.Label(baseFrame, text = "PHP是最好的编程语言,我用python").pack() baseFrame = tkinter.Tk() menubar = tkinter.Menu(baseFrame) for x in ['麻辣香菇', '汽锅鸡', '东坡肘子']: menubar.add_separator() menubar.add_command(label=x) menubar.add_command(label='重庆火锅', command = makeLabel) # 事件处理函数一定要至少有一个参数,且第一个参数表示的是系统事件 def pop(event): # 注意使用event.x和event.x_root的区别 # menubar.post(event.x_root, event.y_root) menubar.post(event.x_root, event.y_root) baseFrame.bind("<Button-3>", pop) baseFrame.mainloop()
- 画布:可以自由的在上面绘制图形的一个小舞台
- 在画布上绘制对象,通常用create_xxx, xxxx=对象类型,例如line,rectangle
- 画布所支持的组件:
- arc
- bitmap
- image(BitmapImage, PhototImage)
- line
- oval
- polyon
- rectangle
- text
- window(组件)
- 每次调用create_xxx都会返回一个创建的组件的ID,同时也可以用tag属性指定其标签
- 通过调用canvas.move实现一个一次性动作
- 实例v13.py
# 简单的画布 import tkinter baseFrame = tkinter.Tk() cvs = tkinter.Canvas(baseFrame, width = 300, height = 200) cvs.pack() # 一条线需要两个点指明起始 # 参数数字的单位是px cvs.create_line(23, 23, 190, 234) cvs.create_text(56, 67, text = "I Love LiuYiFei") baseFrame.mainloop() - 实例v14.py
# 画一个五角星 import tkinter import math as m baseFrame = tkinter.Tk() w = tkinter.Canvas(baseFrame, width = 300, height = 300, background = 'red') w.pack() center_x = 150 center_y = 150 r = 150 # 依次存放五个点的位置 points = [ # 做上点 # pi是一个常量数字,3.1415926 center_x - int(r * m.sin(2 * m.pi / 5)), center_y - int(r * m.cos(2 * m.pi / 5)), # 右上点 center_x + int(r * m.sin(2 * m.pi / 5)), center_y - int(r * m.cos(2 * m.pi / 5)), # 左下点 center_x - int(r * m.sin(m.pi / 5)), center_y + int(r * m.cos(m.pi / 5)), # 顶点 center_x, center_y - r, # 右下点 center_x + int(r * m.sin(m.pi / 5)), center_y + int(r * m.cos(m.pi /5)), ] # 创建一个多边形 w.create_polygon(points, outline="green", fill = "yellow") w.create_text(150, 150, text = "五角星") baseFrame.mainloop() - 实例v15.py
import tkinter baseFrame = tkinter.Tk() def btnClick(event): global w w.move(id_ball, 12, 5) w.move("fall", 0, 5) w = tkinter.Canvas(baseFrame, width = 500, height = 400) w.pack() w.bind("<Button-1>", btnClick) # 创建组件后返回id id_ball = w.create_oval(20, 20, 50, 50, fill = "green") # 创建组件使用tag属性 w.create_text(123, 56, fill = "red", text = "I Love LiuYiFei", tag = "fall") # 创建的时候如果没有指定tag可以利用addtag_withtag添加 # 同类函数还有addtag_all, addtag_above, addtag_xxx等等 id_rectangle = w.create_rectangle(56, 78, 173, 110, fill = "gray") w.addtag_withtag("fall", id_rectangle) baseFrame.mainloop()
版权声明:本文为qq_42471503原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。