赞
踩
大家好,小编为大家解答python图形用户界面方向的第三方库的问题。很多人还不知道python用户图形界面第三方库,现在让我们一起来看看吧!
如果对您有一丁点帮助,劳烦动动手指点个赞,支持和鼓励是搬砖人不断创作的动力!
我们前面实现的都是基于控制台的程序,程序和用户的交 互通过控制台来完成。
本章,我们将学习 GUI(Graphics User Interface), 即图形用户界面编程,我们可以通过 python 提供的丰富的 组件,快速的实现使用图形界面和用户交互用python画笑脸代码。
GUI编程类似于“搭积木”,将一个个组件(Widget)放到 窗口中。如下是 windows 中的画图软件,就是一个典型的 GUI程序:
上面的各种按钮、菜单、编辑区域等都是一个个组件,它 们都放置到窗口中,并通过增加“对事件的处理”成为一个 完整的程序。
常用的 GUI 库
tkinter(Tk interface)是 Python 的标准 GUI库,支持跨 平台的 GUI程序开发。tkinter 适合小型的 GUI程序编写, 也特别适合初学者学习 GUI编程。本书以 tkinter 为核心进 行讲解。
wxPython 是比较流行的 GUI库,适合大型应用程序开发, 功 能 强 于 tkinter, 整 体 设 计 框 架 类 似 于 MFC(Microsoft Foundation Classes 微软基础类库)。
Qt 是一种开源的 GUI库,适合大型 GUI程序开发,PyQT 是 Qt 工 具 包 标 准 的 Python 实 现 。 我 们 也 可 以 使 用 Qt Desginer 界面设计器快速开发 GUI应用程序。
本章中,涉及大量的 API讲解。学习 API最好的来源就是 官方提供的文档:tkinter 官方网址:
Graphical User Interfaces with Tk — Python 3.7.17 documentation
或者:http://effbot.org/tkinterbook/ 初学者查找)
(相对规整,适合
btn01 = Button(root)
基于 tkinter 模块创建 GUI程序包含如下 4 个核心步骤:
- fromtkinter import *
- root = Tk()
- btn01 = Button(root)
- btn01["text"]= "点我就送花"
- def songhua(e):
- messagebox.showinfo("Message","送你一朵玫瑰花,请 你爱上我")
- print("送你 99 朵玫瑰花")
- btn01.bind("<Button- 1>",songhua)
【示例】使用 tkinter 模块,创建 GUI应用程序,并实现点 击按钮的事件处理
- from tkinter import *
-
- from tkinter import messagebox
-
- root = Tk()
-
- btn01 = Button(root)
- btn01["text"]= "点我就送花"
- btn01.pack()
-
- def songhua(e):
- messagebox.showinfo("Message","送你一朵玫瑰花,请你爱 上我")
- print("送你 99 朵玫瑰花")
-
- btn01.bind("<Button- 1>",songhua)
- root.mainloop() #调用组件的 mainloop 方法,进入事 件循环
通过 geometry(‘wxh±x±y’)进行设置。w 为宽度,h 为高度。 +x 表示距屏幕左边的距离;-x 表示距屏幕右边的距离;+y 表示距屏幕上边的距离;-y 表示距屏幕下边的距离。
【示例】测试 tkinter 主窗口位置和大小的设置 fromtkinter import *
root = Tk()
root.title(“测试主窗口的位置和大小”) root.geometry(“500x400+100+200”) #宽度 500,高度 400;距 屏幕左边 100,距屏幕上边 200
root.mainloop() 执行结果:
图形用户界面是由一个个组件组成,就像小孩“搭积木”一样最终组成了整个界面。有 的组件还能在里面再放置其他组件,我们称为“容器”。Tkinter 的 GUI组件关系图如下:
图 tkinter 中 GUI组件的继承关系图 根据上图所示,我们依次讲解这些类的基本作用。
·Misc 和 Wm:
Tkinter 的 GUI 组件有两个根父类,它们都直接继承了 object 类: ·Misc:它是所有组件的根父类。 ·Wm:它主要提供了一些与窗口管理器通信的功能函数。
·Tk
Misc 和 Wm 派生出子类 Tk,它代表应用程序的主窗口。一般应用程序都需要直接或间 接使用 Tk。
·Pack、Place、Grid
Pack、Place、Grid 是布局管理器。布局管理器管理组件的:大小、位置。通过布局管 理器可以将容器中的组件实现合理的排布。
·BaseWidget
BaseWidget 是所有组件的父类
·Widget
Widget 是所有组件类的父类。Widget 一共有四个父类:BaseWidget、Pack、Grid、 Place。意味着,所有 GUI组件同时具备这四个父类的属性和方法。
【 注 】 想 观 察 类 的 层 次 结 构 可 以 在 类 定 义 处 的 类 名 上 单 击 右 键 , 选 择 Diagram–>show Diagram。
Tkinter 类 | 名称 | 简介 |
---|---|---|
Toplevel | 顶层 | 容器类,可用于为其他组件提供单独的容器;Toplevel 有点 类似于窗口 |
Button | 按钮 | 代表按钮组件 |
Canvas | 画布 | 提供绘图功能,包括直线、矩形、椭圆、多边形、位图等 |
Checkbutton | 复选框 | 可供用户勾选的复选框 |
Entry | 单行输入框 | 用户可输入内容 |
Frame | 容器 | 用于装载其它 GUI 组件 |
Label | 标签 | 用于显示不可编辑的文本或图标 |
LabelFrame | 容器 | 也是容器组件,类似于 Frame,但它支持添加标题 |
Listbox | 列表框 | 列出多个选项,供用户选择 |
Menu | 菜单 | 菜单组件 |
Menubutton | 菜单按钮 | 用来包含菜单的按钮(包括下拉式、层叠式等) |
OptionMenu | 菜单按钮 | Menubutton 的子类,也代表菜单按钮,可通过按钮打开一个 菜单 |
Message | 消息框 | 类似于标签,但可以显示多行文本;后来当 Label 也能显示 |
多行文本之后,该组件基本处于废弃状态 | ||
---|---|---|
PanedWindow | 分区窗口 | 该容器会被划分成多个区域,每添加一个组件占一个区域, 用户可通过拖动分隔线来改变各区域的大小 |
Radiobutton | 单选钮 | 可供用户点边的单选钮 |
Scale | 滑动条 | 拖动滑块可设定起始值和结束值,可显示当前位置的精确值 |
Spinbox | 微调选择器 | 用户可通过该组件的向上、向下箭头选择不同的值 |
Scrollbar | 滚动条 | 用于为组件(文本域、画布、列表框、文本框)提供滚动功 能 |
Text | 多行文本框 | 显示多行文本 |
本节程序也是 GUI应用程序编写的一个主要结构,采用 了面向对象的方式,更加合理的组织代码。
通 过 类 Application 组 织 整 个 GUI 程 序 , 类 Application 继承了 Frame 及通过继承拥有了父类的特性。通过构造函数 __init__()初始化窗口中的对象,通过 createWidgets()方法创 建窗口中的对象。
Frame 框架是一个 tkinter 组件,表示一个矩形的区域。 Frame 一般作为容器使用,可以放置其他组件,从而实现复 杂的布局。
【示例】标准的 GUI程序类的写法
- """测试一个经典的_GUI_程序的写法,使用面向对象的方式"""
-
- from tkinter import *
- from tkinter import messagebox
-
- class Application(Frame):
- """一个经典的_GUI_程序的类的写法"""
- def __init__(self, master=None):
- super().__init__(master) # super()代表的是父类的定义,而不是父类对象
- self.master = master
- self.pack()
- self.createWidget()
- def createWidget(self):
- """创建组件"""
- self.btn01 = Button(self)
- self.btn01["text"] = "点击送花"
- self.btn01.pack()
- self.btn01["command"]= self.songhua
- # 创建一个退出按钮
- self.btnQuit = Button(self, text ="退出", command=root.destroy)
- self.btnQuit.pack()
-
- def songhua(self):
- messagebox.showinfo("送花", "送你99朵玫瑰花")
-
- if name == 'main':
- root = Tk()
- root.geometry("400x100+200+300")
- root.title("一个经典的GUI程序类的测试")
- app = Application(master=root)
- root.mainloop()
Label(标签)主要用于显示文本信息,也可以显示图像。
Label(标签)有这样一些常见属性:
指定字体和字体大小,如:font = (font_name,size)
显示在 Label上的图像,目前 tkinter 只支持 gif格式。
fg 和 bg
fg(foreground):前景色、bg(background):背景色
justify
针对多行文字的对齐,可设置 justify 属性,可选值"left", “center” or “right”
【示例】Label(标签)的用法
- """测试_Label_组件的基本用法,使用面向对象的方式"""
- from tkinter import *
- class Application(Frame):
- def __init__(self, master=None):
- super().__init__(master) # super()代表的是父类的定义,而不是父类对象
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(self):
- """创建组件"""
- self.label01 = Label(self, text="百战程序员", width=10, height=2,
- bg="black", fg="white")
- self.label01["text"] ="ccc"
- self.label01.config(fg="red", bg="green")
- self.label01.pack()
- self.label02 = Label(self, text="高淇老师",
- width=10, height=2,
- bg="blue", fg="white", font=("黑体", 30) )
- self.label02.pack()
-
- # 显示图片
- global photo # 把photo声明成全局变量。如果是局部变量,本方法执行完毕后,图像对象销毁,窗口显示不出图片。
- photo = PhotoImage(file="imgs/logo.gif")
- self.label03 = Label(self, image=photo)
- self.label03.pack()
- self.label04 = Label(self, text="北京尚学堂\n百战程序员\n老高好帅,就是做饭不行",
- borderwidth=5, relief="groove", justify="right")
- self.label04.pack()
-
- if name == 'main':
- root = Tk()
- root.geometry("400x260+200+300")
- app = Application(master=root)
- root.mainloop()
运行结果如下:
通过学习 Label组件,我们发现可以通过 Options 设置组件的属性,从而控制组件的各 种状态。比如:宽度、高度、颜色、位置等等。
我们可以通过三种方式设置 Options 选项,这在各种 GUI组件中用法都一致。
fred = Button(self, fg=“red”, bg=“blue”)
fred[“fg”]= “red” fred[“bg”]= “blue”
如何查看组件的 Options 选项:
我们可以看到如下的代码:
- class Button(Widget):
-
- """Button widget."""
- def__init__(self, master=None, cnf={}, \*\*kw):
- """Construct a button widget with the parent MASTER.
- STANDARDOPTIONS
- activebackground, activeforeground, anchor, background, bitmap, borderwidth, cursor, disabledforeground, font, foreground highlightbackground, highlightcolor, highlightthickness, image, justify,
- padx, pady, relief, repeatdelay, repeatinterval, takefocus, text,
- textvariable, underline, wraplength
- WIDGET- SPECIFICOPTIONS
- command, compound, default, height, overrelief, state, width
- """
-
- Widget.__init__(self, master, 'button', cnf, kw)
上面代码中有:“standard options 标准选项”和“widget-specific options 组件特定选项”。 我们将常见的选项汇总如下:
选项名(别名) | 含义 |
---|---|
activebackground | 指定组件处于激活状态时的背景色 |
activeforeground | 指定组件处于激活状态时的前景色 |
anchor | 指定组件内的信息(比如文本或图片)在组件中如何显示(当所在组件比信 息大时,可以看出效果)。必须为下面的值之一:N、NE、E、SE、S、SW W、NW或 CENTER。比如 NW(NorthWest)指定将信息显示在组件的左 上角 |
background(bg) | 指定组件正常显示时的背景色 |
bitmap | 指定在组件上显示该选项指定的位图,该选项值可以是 Tk_GetBitmap 接收的任何形式的位图。位图的显示方式受 anchor、justify选项的影响。如果 同时指定了 bitmap 和 text,那么 bitmap 覆盖文本;如果同时指定了 bitmap 和 image,那么 image 覆盖 bitmap |
borderwidth | 指定组件正常显示时的 3D边框的宽度,该值可以是 Tk_GetPixels 接收的任 何格式 |
cursor | 指定光标在组件上的样式。该值可以是 Tk_GetCursors 接受的任何格式 |
command | 指定按组件关联的命令方法,该方法通常在鼠标离开组件时被触发调用 |
disabledforeground | 指定组件处于禁用状态时的前景色 |
font | 指定组件上显示的文本字体 |
foreground(fg) | 指定组件正常显示时的前景色 |
highlightbackground | 指定组件在高亮状态下的背景色 |
highlightcolor | 指定组件在高亮状态下的前景色 |
highlightthickness | 指定组件在高亮状态下的周围方形区域的宽度,该值可以是 Tk_GetPixels 接收的任何格式 |
height | 指定组件的高度,以 font 选项指定的字体的字符高度为单位,至少为 1 |
image | 指定组件中显示的图像,如果设置了 image 选项,它将会覆盖 text、bitmap 选项 |
justify | 指定组件内部内容的对齐方式,该选项支持 LEFT(左对齐)、CENTER(居 中对齐)或 RIGHT(右对齐)这三个值 |
padx | 指定组件内部在水平方向上两边的空白,该值可以是 Tk_GctPixels 接收的 任何格式 |
pady | 指定组件内部在垂直方向上两地的空白,该值可以是 Tk_GctPixels 接收的 任何格式 |
relief | 指定组件的 3D 效果,该选项支持的值包括 RAISED、SUNKEN、FLAT、 RIDGE、SOLID、GROOVE。该值指出组件内部相对于外部的外观样式, 比如 RAISED表示组件内部相对于外部凸起 |
selectbackground | 指定组件在选中状态下的背景色 |
selectborderwidth | 指定组件在选中状态下的 3D边框的宽度,该值可以是 Tk_GetPixels 接收的 任何格式 |
selectforeground | 指定组在选中状态下的前景色 |
state | 指定组件的当前状态。该选项支持 NORMAL(正常)、DISABLE(禁用) 这两个值 |
takefocus | 指定组件在键盘遍历(Tab 或 Shift+Tab)时是否接收焦点,将该选项设为 1 表示接收焦点;设为 0 表示不接收焦点 |
text | 指定组件上显示的文本,文本显示格式由组件本身、anchor 及 justify 选 项决定 |
textvariable | 指定一个变量名,GUI 组件负责显示该变量值转换得到的字符串,文本显 示格式由组件本身、anchor 及 justify 选项决定 |
underline | 指定为组件文本的第几个字符添加下画线,该选项就相当于为组件绑定了 快捷键 |
width | 指定组件的宽度,以 font 选项指定的字体的字符高度为单位,至少为 1 |
wraplength | 对于能支持字符换行的组件,该选项指定每行显示的最大字符数,超过该 |
数量的字符将会转到下行显示 | |
xscrollcommand | 通常用于将组件的水平滚动改变(包括内容滚动或宽度发生改变)与水平 滚动条的 set 方法关联,从而让组件的水平滚动改变传递到水平滚动条 |
yscrollcommand | 通常用于将组件的垂直滚动改变(包括内容滚动或高度发生改变)与垂直 滚动条的 set 方法关联,从而让组件的垂直滚动改变传递到垂直滚动条 |
Button(按钮)用来执行用户的单击操作。Button 可以包含 文本,也可以包含图像。按钮被单击后会自动调用对应事件 绑定的方法。
【示例】Button 按钮用法(文字、图片、事件)
- """*测试_Button_组件的基本用法,使用面向对象的方式*"""
-
- from tkinter import *
- from tkinter import messagebox
-
- class Application(Frame):
-
- def __init__(self, master=None):
- super().__init__(master) # super()代表的是父类的定义,而不是父类对象
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(self):
- """*创建组件*"""
- self.btn01 = Button(root, text="登录",
- width=6, height=3, anchor=NE, command=self.login)
- self.btn01.pack()
-
- global photo
- photo = PhotoImage(file="imgs/start.gif")
- self.btn02 = Button(root, image=photo, command=self.login)
- self.btn02.pack()
- self.btn02.config(state="disabled") # 设置按钮为禁用
-
- def login(self):
- messagebox.showinfo("尚学堂学习系统", "登录成功!欢迎开始学习!")
-
- if __name__ == '__main__':
- root = Tk()
- root.geometry("400x130+200+300")
- app = Application(master=root)
- root.mainloop()
运行结果:
Entry 用来接收一行字符串的控件。如果用户输入的文字 长度长于 Entry 控件的宽度时, 文字会自动向后滚动。如果 想输入多行文本, 需要使用 Text 控件。
【示例】Entry 单行文本框实现简单登录界面
- """*测试_Entry_组件的基本用法,使用面向对象的方式*"""
-
- from tkinter import *
- from tkinter import messagebox
-
- class Application(Frame):
-
- def __init__(self, master=None):
- super().__init__(master)
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(self):
- """*创建登录界面组件*"""
- self.label01 = Label(self, text="用户名")
- self.label01.pack()
-
- # StringVar变量绑定到指定的组件。
- # StringVar变量的值发生变化,组件内容也变化;
- # 组件内容发生变化,StringVar变量的值也发生变化。
- v1 = StringVar()
-
- self.entry01 = Entry(self, textvariable=v1)
- self.entry01.pack()
-
- v1.set("admin")
- print(v1.get()); print(self.entry01.get())
-
- # 创建密码框
- self.label02 = Label(self, text="密码")
- self.label02.pack()
-
- v2 = StringVar()
- self.entry02 = Entry(self, textvariable=v2, show="*")
- self.entry02.pack()
-
- Button(self, text="登录", command=self.login).pack()
-
- def login(self):
- username = self.entry01.get()
- pwd = self.entry02.get()
-
- print("去数据库比对用户名和密码!")
- print("用户名:"+username)
- print("密码:"+pwd)
-
- if username=="gaoqi" and pwd=="123456":
- messagebox.showinfo("尚学堂学习系统", "登录成功!欢迎开始学习!")
- else:
- messagebox.showinfo("尚学堂学习系统", "登录失败!用户名或密码错误!")
-
- if __name__ == '__main__':
- root = Tk()
- root.geometry("400x130+200+300")
- app = Application(master=root)
- root.mainloop()
界面效果:
Text(多行文本框)的主要用于显示多行文本,还可以显示 网页链接, 图片, HTML 页面, 甚至 CSS 样式表,添加组件 等。因此,也常被当做简单的文本处理器、文本编辑器或者 网页浏览器来使用。比如 IDLE 就是 Text 组件构成的。
【示例】Text 多行文本框基本用法(文本输入、组件和图像 显示)
- """*测试_Text_多行文本框组件的基本用法,使用面向对象的方式*"""
-
- from tkinter import *
- import webbrowser
-
- class Application(Frame):
-
- def __init__(self, master=None):
- super().__init__(master)
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(self):
- self.w1 = Text(root, width=40, height=12, bg="gray")
- # 宽度20个字母(10个汉字),高度一个行高
- self.w1.pack()
-
- self.w1.insert(1.0, "0123456789\nabcdefg")
- self.w1.insert(2.3, "锄禾日当午,汗滴禾下土。谁知盘中餐,粒粒皆辛苦\n")
-
- 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] ')
-
- self.w1.insert(1.8, "gaoqi ")
-
- def returnText(self):
- # Indexes索引是用来指向Text组件中文本的位置,Text的组件索引也是对应实际字符之间的位置。
- # 核心:行号以1开始 列号以0开始
- print(self.w1.get(1.2, 1.6))
- print("所有文本内容:\n"+self.w1.get(1.0, END))
-
- def addImage(self):
- # global photo
- self.photo = PhotoImage(file="imgs/logo.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!\n北京尚学堂\n百战程序员\n百度,搜一下就知道")
-
- self.w1.tag_add("good", 1.0, 1.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")
-
- if __name__ == '__main__':
- root = Tk()
- root.geometry("450x300+200+300")
- app = Application(master=root)
- root.mainloop()
运行结果:
利用 Tags 实现更加强大的文本显示和控制
Tags 通常用于改变 Text 组件中内容的样式和功能。你 可以修改文本的字体、尺寸和颜色。另外,Tags 还允许你 将文本、嵌入的组件和图片与鼠标和键盘等事件相关联。 【示例】利用 Tag 属性实现更复杂文本控制
- #coding=utf- 8
-
- fromtkinter import \*
- import webbrowser
-
- root = Tk();root.geometry("300x300+400+400")
- w1 = Text(root,width=40,height=20) #宽度 20 个字母(10 个汉 字),高度一个行高![ref7]
- w1.pack()
- w1.insert(INSERT,"good good study,daydayup!\n 百度,搜一下就知道") w1.tag\_add("good",1.0,1.9) w1.tag\_config("good",background="yellow",foreground="red")
- w1.tag\_add("baidu",4.0,4.2) w1.tag\_config("baidu",underline=True)
- defwebshow(event):
- webbrowser.open("http://www.baidu.com")
- w1.tag\_bind("baidu","<Button- 1>",webshow) root.mainloop()
运行结果:
点击“百度”后,系统默认浏览器打开百度页面。
Radiobutton 控 件 用 于 选 择 同 一 组 单 选 按 钮 中 的 一 个 。 Radiobutton 可以显示文本,也可以显示图像。
【示例】Radiobutton 基础用法
- """*测试_Radiobutton_组件的基本用法,使用面向对象的方式*"""
-
- from tkinter import *
- from tkinter import messagebox
-
- class Application(Frame):
-
- def __init__(self, master=None):
- super().__init__(master) # super()代表的是父类的定义,而不是父类对象
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(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())
-
- if __name__ == '__main__':
- root = Tk()
- root.geometry("400x50+200+300")
- app = Application(master=root)
- root.mainloop()
运行结果:
Checkbutton 控件用于选择多个按钮的情况。Checkbutton 可以显示文本,也可以显示图像。
【示例】Checkbutton 复选按钮用法
- """*测试_Checkbutton_组件的基本用法,使用面向对象的方式*"""
-
- from tkinter import *
- from tkinter import messagebox
-
- class Application(Frame):
-
- def __init__(self, master=None):
- super().__init__(master)
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(self):
- self.codeHobby = IntVar()
- self.videoHobby = IntVar()
- print(self.codeHobby.get()) # 默认值是0
-
- self.c1 = Checkbutton(self, text="敲代码", variable=self.codeHobby,
- onvalue=1, offvalue=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("测试", "抓获野生程序猿一只,赶紧送给他尚学堂的视频充饥")
-
- if __name__ == '__main__':
- root = Tk()
- root.geometry("400x50+200+300")
- app = Application(master=root)
- root.mainloop()
运行结果:
canvas(画布)是一个矩形区域,可以放置图形、图像、 组件等。本节我们简单介绍 canvas 的使用,更加详细和深 入的内容将在后面的“图形绘制”章节讲解。
【示例】canvas 画布使用基础示例
- """*测试_Canvas_组件的基本用法,使用面向对象的方式*"""
-
- from tkinter import *
- from tkinter import messagebox
- import random
-
- class Application(Frame):
-
- def __init__(self, master=None):
- super().__init__(master)
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(self):
- self.canvas = Canvas(self, width=300, height=200, bg="green")
- self.canvas.pack()
-
- # 画一条直线
- line = self.canvas.create_line(10, 10, 30, 20, 40, 50)
-
- # 画一个矩形
- rect = self.canvas.create_rectangle(50, 50, 100, 100)
-
- # 画一个椭圆。坐标两双。为椭圆的边界矩形左上角和底部右下角
- oval = self.canvas.create_oval(50, 50, 100, 100)
-
- global photo
- photo = PhotoImage(file="imgs/logo.gif")
- self.canvas.create_image(150, 170, image=photo)
-
- Button(self, text="画10个矩形", command=self.draw50Recg).pack(side="left")
-
- def draw50Recg(self):
- for i in range(0, 10):
- x1 = random.randrange(int(self.canvas["width"]) / 2)
- y1 = random.randrange(int(self.canvas["height"]) / 2)
- x2 = x1 + random.randrange(int(self.canvas["width"]) / 2)
- y2 = y1 + random.randrange(int(self.canvas["height"]) / 2)
- self.canvas.create_rectangle(x1, y1, x2, y2)
-
- if __name__ == '__main__':
- root = Tk()
- root.geometry("400x300+200+300")
- app = Application(master=root)
- root.mainloop()
运行结果:
一个 GUI应用程序必然有大量的组件,这些组件如何排 布?这时候,就需要使用 tkinter 提供的布局管理器帮助我们 组织、管理在父组件中子组件的布局方式。tkinter 提供了三 种管理器:pack、grid、place。
grid 布 局 管 理 器
grid 表格布局,采用表格结构组织组件。子组件的位置由 行和列的单元格来确定,并且可以跨行和跨列,从而实现复 杂的布局。
grid()方法提供的选项
选项 | 说明 | 取值范围 |
---|---|---|
column | 单元格的列号 | 从 0 开始的正整数 |
columnspan | 跨列,跨越的列数 | 正整数 |
row | 单元格的行号 | 从 0 开始的正整数 |
rowspan | 跨行,跨越的行数 | 正整数 |
ipadx, ipady | 设置子组件之间的间隔,x 方向或者 y 方向, 默认单位为像素 | 非负浮点数,默认 0.0 |
padx, pady | 与之并列的组件之间的间隔,x 方向或者 y 方向,默认单位是像素 | 非负浮点数,默认 0.0 |
sticky | 组件紧贴所在单元格的某一角,对应于东南 西北中以及 4 个角 | “n”, “s”, “w”, “e”, “nw”, “sw”, “se”, “ne”, “center”(默认) |
【示例】grid 布局用法-登录界面设计
- """*测试_Grid_布局管理器的基本用法,使用面向对象的方式*"""
-
- from tkinter import *
- from tkinter import messagebox
- import random
-
- class Application(Frame):
-
- def __init__(self, master=None):
- super().__init__(master)
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(self):
- """*通过grid布局实现登录界面*"""
- self.label01 = Label(self, text="用户名")
- self.label01.grid(row=0, column=0)
-
- self.entry01 = Entry(self)
- self.entry01.grid(row=0, column=1)
-
- Label(self, text="用户名为手机号\n").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)
-
- if __name__ == '__main__':
- root = Tk()
- root.geometry("400x90+200+300")
- app = Application(master=root)
- root.mainloop()
运行结果:
【示例】通过 grid 布局-实现计算器软件界面。 根据实际简易计算器的按键分布,设计一个相仿的计算器界 面,相应的功能暂不需要实现。
如上界面,实际可以设计成一个 7 行 4 列的表格布局,然后 将相应的按钮放置进去即可。
- """*计算器软件界面的设计*"""
-
- from tkinter import *
- from tkinter import messagebox
- import random
-
- class Application(Frame):
-
- def __init__(self, master=None):
- super().__init__(master)
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(self):
- """*通过grid布局实现计算器的界面*"""
- btnText = (("MC", "M+", "M-", "MR"),
- ("C", "±", "/", "✖"),
- (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):
- 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, column=cindex, columnspan=2, 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)
-
- if __name__ == '__main__':
- root = Tk()
- root.geometry("200x200+200+300")
- app = Application(master=root)
- root.mainloop()
pack按照组件的创建顺序将子组件添加到父组件中,按 照垂直或者水平的方向自然排布。如果不指定任何选项,默 认在父组件中自顶向下垂直添加组件。
pack 是代码量最少,最简单的一种,可以用于快速生成
界面。
pack()方法提供的选项
名称 | 描述 | 取值范围 |
---|---|---|
expand | 当值为“yes”时,side 选项无效。组件显示在父配件中心位置;若 fill 选项为”both”,则填充父组件的剩余空间 | “yes”, 自然数,”no”, 0(默认值”no” 或 0) |
fill | 填充 x(y)方向上的空间,当属性 side=”top”或”bottom”时,填充 x 方向;当属性 side=”left”或”right”时,填充”y”方向;当 expand 选 项为”yes”时,填充父组件的剩余空间 | “x”, “y”, “both”,“none” (默认值为 none) |
ipadx, ipady | 设置子组件之间的间隔,x 方向或者 y 方向,默认单位为像素 | 非负浮点数,默认 0.0 |
padx, pady | 与之并列的组件之间的间隔,x 方向或者 y 方向,默认单位是像素 | 非负浮点数,默认 0.0 |
side | 定义停靠在父组件的哪一边上 | “top”,“bottom”,“left”,“right” (默认为”top”) |
before | 将本组件于所选组建对象之前 pack,类似于先创建本组件再创建选定 组件 | 已经 pack 后的组件对象 |
after | 将本组件于所选组建对象之后 pack,类似于先创建选定组件再本组件 | 已经 pack 后的组件对象 |
in_ | 将本组件作为所选组建对象的子组件,类似于指定本组件的 master 为选定组件 | 已经 pack 后的组件对象 |
anchor | 对齐方式,左对齐”w”,右对齐”e”,顶对齐”n”,底对齐”s” | “n”, “s”, “w”, “e”, “nw”, “sw”, “se”, “ne”, “center”(默认) |
【老鸟建议】如上列出了 pack 布局所有的属性,但是不需 要挨个熟悉,了解基本的即可。pack 适用于简单的垂直或水 平排布,如果需要复杂的布局可以使用 grid 或 place。 【示例】pack 布局用法,制作钢琴按键布局
- # coding=utf-8
- """测试 pack 布局管理器"""
-
- from tkinter import *
-
- root = Tk()
- root.geometry("700x220")
-
- # Frame 是一个矩形区域,就是用来防止其他子组件 overflow
- f1 = Frame(root)
- f1.pack()
-
- f2 = Frame(root)
- f2.pack()
-
- btnText = ("流行风", "中国风", "日本风", "重金属", "轻音乐")
-
- for txt in btnText:
- Button(f1, text=txt).pack(side="left", padx=10)
-
- for i in range(1,20):
- Button(f2, width=5, height=10, bg="black" if i%2==0 else "white").pack(side="left")
-
- root.mainloop()
place 布局管理器可以通过坐标精确控制组件的位置,适用于一些布局更加灵活的场景。
place() 方法的选项:
选项 | 说明 | 取值范围 |
---|---|---|
x,y | 组件左上角的绝对坐标 (相对于窗口) | 非负整数 x 和 y 选项用于设置偏移(像素),如果同时设置 relx(rely) 和 x(y),那么 place 将优先计算 relx 和 rely,然后再实现 x 和 y 指定的偏移值 |
relx rely | 组件左上角的坐标 (相对于父容器) | relx 是相对父组件的位置。0 是最左边,0.5 是正中间,1 是最右边; rely 是相对父组件的位置。0 是最上边,0.5 是正中间,1 是最下边; |
width, height | 组件的宽度和高度 | 非负整数 |
relwidth, relheight | 组件的宽度和高度 (相对于父容器) | 与 relx、rely 取值类似,但是相对于父组件的尺寸 |
anchor | 对齐方式,左对齐”w”, 右对齐”e”,顶对齐”n”, 底对齐”s” | “n”, “s”, “w”, “e”, “nw”, “sw”, “se”, “ne”, “center”(默认) |
【示例】place 布局管理-基本用法测试 #coding=utf- 8
- from tkinter import *
-
- root = Tk()
- root.geometry("500x300")
- root.title("布局管理 place")
- root["bg"] = "white"
-
- f1 = Frame(root, width=200, height=200, bg="green")
- f1.place(x=30, y=30)
-
- Button(root, text="尚学堂").place(relx=0.5, rely=0, x=100, y=200, relwidth=0.2, relheight=0.2)
- Button(f1, text="百战程序员").place(relx=0.6, rely=0.7)
- Button(f1, text="高淇老师").place(relx=0.2, rely=0.2)
-
- root.mainloop()
root.mainloop() 运行结果:
【示例】place 布局管理-扑克牌游戏 demo
- """扑克牌游戏的界面设计"""
-
- from tkinter import *
-
- class Application(Frame):
-
- def __init__(self, master=None):
- super().__init__(master) # super()代表的是父类的定义,而不是父类对象
- self.master = master
- self.pack()
- self.createWidget()
-
- def createWidget(self):
- """通过place布局管理器实现扑克牌位置控制"""
-
- # self.photo = PhotoImage(file="imgs/puke/puke1.gif")
- # self.puke1 = Label(self.master, image=self.photo)
- # self.puke1.place(x=10, y=50)
-
- self.photos = [PhotoImage(file="imgs/puke/puke"+str(i+1)+".gif") for i in range(10)]
- self.pukes = [Label(self.master, image=self.photos[i]) for i in range(10)]
-
- for i in range(10):
- self.pukes[i].place(x=10+i*40, y=50)
-
- # 为所有的Label增加事件处理
- self.pukes[0].bind_class("Label", "<Button-1>", self.chupai)
-
- def chupai(self, event):
- print(event.widget.winfo_geometry())
- print(event.widget.winfo_y())
- if event.widget.winfo_y() == 50:
- event.widget.place(y=30)
- else:
- event.widget.place(y=50)
-
- if __name__ == '__main__':
- root = Tk()
- root.geometry("600x270+200+300")
- app = Application(master=root)
- root.mainloop()
一 个 GUI 应 用 整 个 生 命 周 期 都 处 在 一 个 消 息 循 环 (event loop) 中。它等待事件的发生,并作出相应的处理。
Tkinter 提供了 用以处理相 关事件的机 制. 处理函 数可被绑 定给各个控件的各种事件。
widget.bind(event, handler)
如 果 相 关 事 件 发 生 , handler 函 数 会 被 触 发 , 事 件 对 象 event 会传递给 handler 函数.
代码 | 说明 |
---|---|
<1> | 鼠标左键按下。 2 表示右键,3 表示中键; |
鼠标左键释放 | |
按住鼠标左键移动 | |
双击左键 | |
鼠标指针进入某一组件区域 | |
鼠标指针离开某一组件区域 | |
滚动滚轮; | |
按下 a 键,a 可用其他键替代 | |
释放 a 键。 | |
按下 A键(大写的 A) | |
同时按下 alt 和 a;alt 可用 ctrl和 shift 替代 | |
快速按两下 a | |
CTRL 和 V键被同时按下,V可以换成其它键位 |
event 对象常用属性
名称 | 说明 |
---|---|
char | 按键字符,仅对键盘事件有效 |
keycode | 按键编码,仅对键盘事件有效 |
keysym | 按键名称,仅对键盘事件有效 比如按下空格键: 键的 char: 键的 keycode:32 比如按下 a 键: 键的 keysym:space 键的 char:a 键的 keycode:65 键的 keysym:a |
num | 鼠标按键,仅对鼠标事件有效 |
type | 所触发的事件类型 |
widget | 引起事件的组件 |
width,height | 组件改变后的大小,仅 Configure 有效 |
x,y | 鼠标当前位置,相对于父容器 |
x_root,y_root | 鼠标当前位置,相对于整个屏幕 |
【示例】鼠标事件和键盘事件用法测试
- from tkinter import *
-
- root = Tk()
- root.geometry("530x300")
-
- c1 = Canvas(root, width=200, height=200, bg="green")
- c1.pack()
-
- def mouseTest(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(event):
- c1.create_oval(event.x, event.y, event.x+1, event.y+1)
-
- def keyboardTest(event):
- print("键的keycode: {0}, 键的char: {1}, 键的keysym: {2}".format(event.keycode, event.char, event.keysym))
-
- def press_a_test(event):
- print("press a")
-
- def release_a_test(event):
- print("release a")
-
- c1.bind("<Button-1>", mouseTest)
- c1.bind("<B1-Motion>", testDrag)
- root.bind("<KeyPress>", keyboardTest)
- root.bind("<KeyPress-a>", press_a_test) # 只针对小写的a,大写的A不管用
- root.bind("<KeyRelease-a>", release_a_test)
- root.mainloop()
lambda 表达式定义的是一个匿名函数,只适合简单输入参 数,简单计算返回结果,不适合功能复杂情况。
lambda 定义的匿名函数也有输入、也有输出,只是没有名 字。语法格式如下:
lambda 参数值列表:表达式
参数值列表即为输入。 表达式计算的结构即为输出。
我们写一个最简单的案例:
add3args = lambda x,y,z:x+y+z #print(add3args(10,20,30))
上面的 lambda 表达式相当于如下函数定义:
defadd3args(x,y,z):
return x+y+z
lambda 表达式的参数值列表可以为如下内容:
lambda 格式 | 说明 |
---|---|
lambda x, y: x*y | 函数输入是 x 和 y,输出是它们的积 x*y |
lambda:None | 函数没有输入参数,输出是 None |
lambda:aaa(3,4) | 函数没有输入参数,输出是 aaa(3,4)的结 果 |
lambda *args: sum(args) | 输入是任意个数的参数,输出是它们的和 |
lambda **kwargs: 1 | 输入是任意键值对参数,输出是 1 |
我们在平时使用时,注意 lambda 只是一个匿名函数(没有
名字的函数),功能不强,不要过度使用;
【示例】使用 lambda 帮助 command 属性绑定时传参
- # coding=utf-8
- """
- 测试 command 属性绑定事件,测试 lambda 表达式帮助传参
- """
-
- from tkinter import *
-
- root = Tk()
- root.geometry("270x50")
-
- def mouseTest1():
- print("command方式,简单情况:不涉及获取event对象,可以使用")
-
- def mouseTest2(a, b):
- print("a={0}, b={1}".format(a, b))
-
- Button(root, text="测试command1", command=mouseTest1).pack(side="left")
-
- Button(root, text="测试command2",
- command=lambda: mouseTest2("gaoqi", "xixi")).pack(side="left")
-
- root.mainloop()
·组件对象的绑定
c1 = Canvas(); c1.bind(“”,drawLine)
·组件类的绑定
调用对象的 bind_class 函数,将该组件类所有的组件绑定事件: w.bind_class(“Widget”,”event”,eventhanler)
比如:btn01.bind_class(“Button”,””,func)
【示例】多种事件绑定方式总结
- # coding=utf-8
- """
- 多种事件绑定方式汇总
- """
-
- from tkinter import *
-
- root = Tk()
- root.geometry("270x30")
-
- def mouseTest1(event):
- print("bind()方式绑定,可以获取event对象")
- print(event.widget)
-
- def mouseTest2(a, b):
- print("a={0}, b={1}".format(a, b))
- print("command方式绑定,不能直接获取event对象")
-
- def mouseTest3(event):
- print("右键单击事件,绑定给所有按钮啦!!")
- print(event.widget)
-
- b1 = Button(root, text="测试bind()绑定")
- b1.pack(side="left")
-
- # bind方式绑定事件
- b1.bind("<Button-1>", mouseTest1)
-
- # command属性直接绑定事件
- b2 = Button(root, text="测试command2",
- command=lambda: mouseTest2("gaoqi", "xixi"))
- b2.pack(side="left")
-
- # 给所有Button按钮都绑定右键单击事件<Button-2>
- b1.bind_class("Button", "<Button-2>", mouseTest3)
-
- root.mainloop()
我们在前面介绍了最常用的几个组件,接下来我们介绍其他 一些组件。
OptionMenu(选 择 项 )用 来 做 多 选 一 , 选 中 的 项 会 在 顶 部 显 示。
【示例】OptionMenu(选择项)的基本用法
- # coding=utf-8
-
- """
- optionmenu 的使用测试
- """
-
- from tkinter import *
-
- root = Tk()
- root.geometry("200x100")
-
- v = StringVar(root)
- v.set("百战程序员")
-
- om = OptionMenu(root, v, "尚学堂", "百战程序员", "卓越班[保底18万]")
- om["width"] = 10
- om.pack(pady=20)
-
- def test1():
- print("最喜爱的机构:", v.get())
-
- # 直接修改了optionmenu中选中的值
- v.set("尚学堂")
-
- Button(root, text="确定", command=test1).pack()
-
- root.mainloop()
运行结果:
Scale(移动滑块)用于在指定的数值区间,通过滑块的移动来
选择值。
【示例】使用 Scale(移动滑块)控制字体大小变化 #coding=utf- 8
- """
- optionmenu 的使用测试
- """
-
- 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, orient=HORIZONTAL, command=test1)
- s1.pack()
-
- a = Label(root, text="百战程序员", width=10, height=1, bg="black", fg="white")
- a.pack()
-
- root.mainloop()
运行结果:
颜色选择框可以帮助我们设置背景色、前景色、画笔颜色、 字体颜色等等。
【示例】颜色选择框基本用法
- # coding=utf-8
-
- """
- askcolor 颜色选择框的测试,改变背景色
- """
-
- from tkinter import *
- from tkinter.colorchooser import *
-
- root = Tk()
- root.geometry("400x150")
-
- def test1():
- s1 = askcolor(color="red", title="选择背景色")
- root.config(bg=s1[1])
-
- Button(root,text="选择背景色",command=test1).pack()
-
- root.mainloop()
运行结果:
文件对话框帮助我们实现可视化的操作目录、操作文件。最 后,将文件、目录的信息传入到程序中。文件对话框包含如 下一些常用函数:
函数名 | 对话框 | 说明 |
---|---|---|
askopenfilename(**op tions) | 文件对话框 | 返回打开的文件名 |
askopenfilenames(**o ptions) | 返 回 打 开 的 多 个 文 件名列表 | |
askopenfile(**options) | 返 回 打 开 的 文 件 对 象 | |
askopenfiles(**option s) | 返 回 打 开 的 文 件 对 象的列表 | |
askdirectory(**options ) | 目录对话框 | 返回目录名 |
asksaveasfile(**option s) | 保存对话框 | 返 回 保 存 的 文 件 对 象 |
asksaveasfilename(** options) | 返回保存的文件名 |
命名参数 options 的常见值如下:
参数名 | 说明 |
---|---|
defaultextension | 默认后缀:.xxx 用户没 有输入则自 动添加 |
filetypes=[(label1, pattern1),(labe2,p attern2)] | 文件显示过滤器 |
initaldir | 初始目录 |
initalfile | 初始文件 |
parent | 父窗口 ,默认根窗 口 |
title | 窗口标题 |
【示例】文件对话框基本用法
运行结果:
【示例】打开指定 txt 文件,并读出文件内容到窗口
- # coding=utf-8
-
- """
- askopenfile 测试选择文件并读取内容
- """
-
- from tkinter import *
- from tkinter.filedialog import *
-
- root = Tk()
- root.geometry("400x100")
-
- def test1():
- with askopenfile(title="上传文件",
- initialdir="d:",
- filetypes=[("文本文件", ".txt")]) as f:
-
- show["text"] = f.read()
-
- Button(root,text="选择编辑的视频文件",command=test1).pack()
-
- show = Label(root, width=40, height=3, bg="green")
- show.pack()
-
- root.mainloop()
simpledialog(简单对话框)包含如下常用函数:
函数名 | 说明 |
---|---|
askfloat(title,promp t,**kw) | 输入并返回浮点数 |
askinteger(title,pro mpt,**kw) | 输入并返回整数 |
askstring(title,prom pt,**kw) | 输入并返回字符串 |
参数中,title 表示窗口标题;prompt 是提示信息;命名参数 kw 为各种选项:initialvalue(初始值)、minvalue(最小值)、 maxvalue(最大值)。
【示例】简单对话框基本用法 #coding=utf- 8 #简单对话框
- from tkinter import *
- from tkinter.simpledialog import *
-
- root = Tk()
- root.geometry("400x100")
-
- show = Label(root, width=40, height=3, bg="green")
- show.pack()
-
- a = askinteger(title="输入年龄",
- prompt="请输入年龄",
- initialvalue=18,
- minvalue=1,
- maxvalue=150)
-
- show["text"] = "年龄:" + str(a)
-
- # askfloat, askstring 自行测试
-
- root.mainloop()
运行结果:
messagebox(通用消息框)用于和用户简单的交互,用户 点击确定、取消。如下列出了 messagebox 的常见函数:
函数名 | 说明 | 例子 |
---|---|---|
askokcancel(title,mess age,**options) | OK/Cancel对 话框 | |
askquestion(title,mess age,**options) | Yes/No 问 题 对话框 | |
askretrycancel(title,me ssage,**options) | Retry/Cancel 问题对话框 | |
showerror(title,messag e,**options) | 错 误 消 息 对 话框 | |
showinfo(title,message ,**options) | 消息框 | |
showwarning(title,mes sage,**options) | 警告消息框 | |
【示例】通用消息框的基本用法 #coding=utf- 8
#简单对话框
- from tkinter import *
- from tkinter.messagebox import *
-
- root = Tk()
- root.geometry("400x100")
-
- a1 = showinfo(title="尚学堂",
- message="Python400集从零开始, 深入底层,\
- 深入算法,打好基础。还手写神经网络")
-
- print(a1)
- root.mainloop()
我们再前面学的组件是 tkinter 模块下的组件,整体风格 较老较丑。为了弥补这点不足,推出了 ttk 组件。ttk 组件更 加 美 观 、 功 能 更 加 强 大 。 使 用 Combobox 替 代 了 原 来 的 Listbox 、 新 增 了 LabeledScale( 带 标 签 的 Scale) 、 Notebook(多文档窗口)、Progressbar(进度条)、Treeview(数) 等组件。
使用 ttk 组件与使用普通的 Tkinter 组件并没有多大的 区别,只要导入 ttk 模块即可。
ttk 子模块的官方文档:
tkinter.ttk — Tk themed widgets — Python 3.7.17 documentation
GUI程序通常都有菜单,方便用户的交互。我们一般将菜单 分为两种:
主菜单通常位于 GUI程序上方。例如:
主菜单一般包含:文件、编辑、帮助等,位于 GUI窗口的上 面。创建主菜单一般有如下 4 步:
menubar = tk.Menu(root)
file_menu = tk.Menu(menubar) menubar.add_cascade(label=”文件”,menu=file_menu)
file_menu.add_separator() file_menu.add_command(label=”退出”)
【示例】记事本软件主菜单设计
- # coding=utf-8
-
- """
- 记事本软件,练习主菜单的设计
- """
-
- from tkinter import *
- from tkinter.messagebox import *
- from tkinter.filedialog import *
-
- root = Tk()
- root.geometry("400x400")
-
- # 创建主菜单栏
- 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)
-
- filename = ""
-
- def openFile():
- global filename
- with askopenfile(title="打开文件") as f:
- content = f.read()
- w1.insert(INSERT, content)
- filename = f.name
- print(f.name)
-
- def saveFile():
- with open(filename, "w") as f:
- content = w1.get(1.0, END)
- f.write(content)
-
- def exit():
- root.quit()
-
- # 添加菜单项
- menuFile.add_command(label="打开", accelerator="^O", command=openFile)
- menuFile.add_command(label="保存", command=saveFile)
- menuFile.add_separator() # 添加分割线
- menuFile.add_command(label="退出", command=exit)
-
- # 将主菜单栏加到根窗口
- root["menu"] = menubar
-
- w1 = Text(root, width=50, height=30)
- w1.pack()
-
- root.mainloop()
运行结果:
快捷菜单(上下文菜单)是通过鼠标右键单击组件而弹出的
菜单,一般是和这个组件相关的操作,比如:剪切、复制、 粘贴、属性等。创建快捷菜单步骤如下:
menubar = tk.Menu(root) menubar.add_command(label=”字体”)
- def test(event):
- menubar.post(event.x_root,event.y_root) #在 鼠 标 右 键单击坐标处显示菜单
- root.bind(“<Button-3>”,test)
【示例】为记事本程序增加快捷菜单
- # coding=utf-8
-
- from tkinter import *
- from tkinter.colorchooser import *
- from tkinter.filedialog import *
-
- root = Tk()
- root.geometry("400x400")
-
- def openAskColor():
- s1 = askcolor(color="red", title="选择背景色")
- root.config(bg=s1[1])
-
- # 创建快捷菜单
- menubar2 = Menu(root)
-
- menubar2.add_command(label="颜色", command=openAskColor)
-
- menuedit = Menu(menubar2, tearoff=0)
- menuedit.add_command(label="剪切")
- menuedit.add_command(label="复制")
- menuedit.add_command(label="粘贴")
-
- menubar2.add_cascade(label="编辑", menu=menuedit)
-
- def test(event):
- # 菜单在鼠标右键单击的坐标处显示
- menubar2.post(event.x_root, event.y_root)
-
- # 编辑区
- w1 = Text(root, width=50, height=30)
- w1.pack()
-
- w1.bind("<Button-3>", test)
-
- root.mainloop()
运行结果:
ID: Txtechcom
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。