今天我们将深入学习GUI图形界面编程tkinter, 了解基础组件的使用方式。
tkinter基础组件
在登上天维巨兽身上的时候, 了不起大吃一惊. 作为堪比一个岛屿的存在, 这个生物的身上好像蕴藏着无数的奥秘. 可是刚一下来迎接他们的不是鲜花和掌声, 而是一把匕首. GBK教信徒蜂拥而至, 由于大家事先都知道这些信徒是被控制的, 因此都特意留手. 尽量都将其击晕, 然后由奥菲利亚通过使用净化魔法来解决. 花费了近一天的时间, 才将近百名被控制的信徒解救成功. 然后在恢复意识的信徒的带领下, 了不起进入到了神殿外围的核心地区. 这里有GBL的大祭司和大神官, 也是奥菲利亚昔日的朋友...
Label 标签
Label(标签)主要用于显示文本信息,也可以显示图像。
常用属性:
- width,height: 用于指定区域大小 如果显示是文本,则以单个英文字符大小为单位(一个汉字宽度占 2 个字符位置,高度和英文字符一样);如果显示是图像,则以像素为单位。默认值是 根据具体显示的内容动态调整
- font: 指定字体和字体大小. 如:font = (font_name,size)
- image: 显示在 Label 上的图像,目前 tkinter 只支持 gif 格式
- fg 和 bg: fg(foreground):前景色、bg(background):背景色
- justify: 针对多行文字的对齐,可设置 justify 属性,可选值"left", "center" or "right"
实操代码:
"""测试 Label 组件的基本用法,使用面向对象的方式"""
from tkinter import *
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="点击label", width=10, height=2, bg="black", fg="white")
self.label01["text"] = "第一个Label"
self.label01.config(fg="red", bg="green")
self.label01.pack()
self.label02 = Label(self, text="第二个Label", width=10, height=2, bg="blue", fg="white", font=("黑体", 30))
self.label02.pack()
# 显示图像
global photo # 把 photo 声明成全局变量. 如果是局部变量,本方法执行完毕后,图像对象销毁,窗口显示不出图像
photo = PhotoImage(file="111.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("600x600+810+330")
root.title("测试Label")
app = Application(master=root)
root.mainloop()
注意:
- Label(标签)主要用于显示文本信息,也可以显示图像
- pack 按照组件的创建顺序将子组件添加到父组件中,按照垂直或者水平的方向自然排布 如果不指定任何选项,默认在父组件中自顶向下垂直添加组件. pack 是代码量最少最简单的一种,可以用于快速生成界面.
Options 选项详解
通过学习 Label 组件,我们发现可以通过 Options 设置组件的属性,从而控制组件的各种状态. 比如:宽度、高度、颜色、位置等等。
可以通过以下三种方式设置 Options 选项,这在各种 GUI 组件中用法都一致:
- 创建对象时,使用可变参数fred = Button(self, fg="red", bg="blue")
- 创建对象后,使用字典索引方式
fred["fg"] = "red"
fred["bg"] = "blue"
- 创建对象后,使用 config()方法 fred.config(fg="red", bg="blue")
如何查看组件的 Options 选项?
- 可以通过打印 config()方法的返回值,查看 Options 选项 print(fred.config())
- 通过在 IDE 中,ctrl+鼠标左键 即可进入组件对象的构造方法,进入到方法内观察:
上面代码中有:“standard options 标准选项”和“widget-specific options 组件特定选项”. 我们将常见的选项汇总如下:
Button 按钮
Button(按钮)用来执行用户的单击操作. Button 可以包含文本,也可以包含图像 按钮被单击后会自动调用对应事件绑定的方法. 相关属性参数介绍见上面Options 选项详解部分图片。
实操代码:
"""
Button(按钮)用来执行用户的单击操作
Button 可以包含文本,也可以包含图像。按钮 被单击后会自动调用对应事件绑定的方法
"""
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self, master):
super().__init__(master) # super()代表的是父类的定义, 而不是父类的对象
self.master = master
self.pack()
self.createWidget()
def createWidget(self):
"""创建组件"""
self.btn01 = Button(root, text="登录", width=4, height=1, anchor=NE, command=self.login)
self.btn01.pack()
global photo
photo = PhotoImage(file="111.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.title("测试Button")
root.geometry("400x400+200+300")
app = Application(master=root)
root.mainloop()
运行结果:
利用 lambda 表达式实现传参
lambda 表达式定义的是一个匿名函数,只适合简单输入参数,简单计算返回结果,不适合功能复杂情况lambda 定义的匿名函数也有输入、也有输出,只是没有名字。
语法格式如下:
lambda 参数值列表:表达式
lambda 表达式的参数值列表可以为如下内容
实操代码:
from tkinter import Tk, Button
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")
"""
lambda 定义的匿名函数也有输入、也有输出,只是没有名字。语法格式如下: lambda 参数值列表:表达式 参数值列表即为输入。 表达式计算的结构即为输出。
"""
Button(root, text="测试 command2", command=lambda: mouseTest2("实参1传入", "实参2传入")).pack(side="left")
root.mainloop()
结果展示:
Entry 单行文本框
Entry 用来接收一行字符串的控件. 如果用户输入的文字长度长于 Entry 控件的宽度时, 文字会自动向后滚动 如果想输入多行文本, 需要使用 Text 控件.
Entry构造函数如下图, 相关属性参数介绍见上面Options 选项详解部分图片:
实操代码:
"""
Entry 用来接收一行字符串的控件。如果用户输入的文字长度长于 Entry 控件的宽度时,
文字会自动向后滚动。如果想输入多行文本, 需要使用 Text 控件。
"""
# 【示例】Entry 单行文本框实现简单登录界面
from tkinter import *
from tkinter import messagebox
class Appliaction(Frame):
def __init__(self, master):
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.btn02 = Label(self, text="密码")
self.pack()
v2 = StringVar()
self.entry02 = Entry(self, textvariable=v2, show="*")
self.entry02.pack()
Button(self, text="登录", command=self.login).pack()
def login(self):
title = "智慧终端学习系统"
username = self.entry01.get()
pwd = self.entry02.get()
print("去数据库对比密码")
print("用户名" + username)
print("密码" + pwd)
if username == "TimePause" and pwd == "123456":
messagebox.showinfo(title, "登陆成功! 欢迎开始学习!")
else:
messagebox.showinfo(title, "登录失败, 用户名密码错误")
if __name__ == "__main__":
root = Tk()
root.title("智慧终端学习系统")
root.geometry("400x130+200+300")
app = Appliaction(master=root)
root.mainloop()
结果展示:
Text 多行文本框
Text(多行文本框)的主要用于显示多行文本,还可以显示网页链接, 图片, HTML 页面, 甚至 CSS 样式表,添加组件等因此,也常被当做简单的文本处理器、文本编辑器或者网 页浏览器来使用。比如 IDLE 就是 Text 组件构成的。
Text 构造函数如下图, 相关属性参数介绍见上面Options 选项详解部分图片:
实操代码:
"""
Text(多行文本框)的主要用于显示多行文本,还可以显示网页链接, 图片, HTML 页面, 甚至 CSS 样式表,添加组件等。
因此,也常被当做简单的文本处理器、文本编辑器或者网 页浏览器来使用。比如 IDLE 就是 Text 组件构成的。
"""
from tkinter import *
import webbrowser
class Application(Frame):
def __init__(self, master=None): # 这里相当于java中定义了一个带参构造. master指代的是一个形参, 为后面创建类的对象时使用
super().__init__(master) # super()代表的是父类的定义,而不是父类对象
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):
self.w1.insert(INSERT, ' 测试插入 ') # INSERT 索引表示在光标处插入
self.w1.insert(END, '测试尾插') # END 索引号表示在最后插入
self.w1.insert(1.8, "测试指定位置插入") # Indexes(索引)是用来指向 Text 组件中文本的位置,Text 的组件索引也是对应实际字符之间的位置
def returnText(self):
print(self.w1.get(1.2, 1.6))
print("所有文本内容:\n" + self.w1.get(1.0, END)) # 核心:行号以 1 开始 列号以 0 开始
def addImage(self):
global photo
self.photo = PhotoImage(file="111.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 webshow(self):
webbrowser.open("http://www.baidu.com")
def testTag(self):
self.w1.delete(1.0, END)
self.w1.insert(INSERT, "good good study,day day up!\n 测试 baidu\n Tag标签\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.1, 4.3)
self.w1.tag_config("baidu", underline=True)
self.w1.tag_bind("baidu", "<Button-1>", self.webshow)
if __name__ == '__main__':
root = Tk()
root.title("测试多行文本text")
root.geometry("450x300+200+300")
app = Application(master=root)
root.mainloop()
结果展示:
Radiobutton 单选按钮
Radiobutton 控件用于选择同一组单选按钮中的一个, 可以显示文本,也可以 显示图像。
实操代码:
"""测试 Radiobutton 组件的基本用法,使用面向对象的方式"""
from tkinter import Frame, Radiobutton, Button, messagebox, Tk, StringVar
class Application(Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack()
self.createWidget()
def createWidget(self): # 定义组件
self.v1 = StringVar()
self.v1.set("F")
self.r1 = Radiobutton(self, text="男性", value="M", variable=self.v1) # 定义单选框
self.r2 = Radiobutton(self, text="女性", value="F", variable=self.v1)
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.v1.get()) # 定义弹窗信息
if __name__ == '__main__':
root = Tk()
root.geometry("400x50+200+300")
app = Application(root)
root.mainloop()
结果展示:
Checkbutton 复选按钮
Checkbutton 控件用于选择多个按钮的情况. 可以显示文本,也可以显示图像。
实操代码:
"""测试 Checkbutton 组件的基本用法,使用面向对象的方式"""
from tkinter import Frame, IntVar, Checkbutton, Button, messagebox, Tk
class Application(Frame):
# 创建构造方法
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.createWidget()
# 创建组件, 创建复选框并设置属性.
def createWidget(self):
self.codeHobby = IntVar()
self.videoHobby = IntVar()
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")
# 创建确定按钮并创建对象的提示框
self.b = Button(self, text="确定", command=self.showInfo).pack(side="left") # 这里command传入的是方法的对象
def showInfo(self):
if self.codeHobby.get() == 1 and self.videoHobby.get() == 1:
messagebox.showinfo("提示框", "既爱看视频又爱学习, 来我这里学编程吧")
elif self.codeHobby.get() == 1: # IntVar需要调用get方法才能获得
messagebox.showinfo("提示框", "你这个人爱学习编程啊, 学python吧")
elif self.videoHobby.get() == 1:
messagebox.showinfo("提示框", "你这个人比较爱看视频啊, 少看点")
else:
messagebox.showinfo("提示框", "啥都不爱啊, 随便选一个作为你的爱好吧")
# 启动方法以及相关组件信息
if __name__ == "__main__":
root = Tk()
root.geometry("400x50+200+300")
app = Application(root)
root.mainloop()
结果展示:
canvas 画布
canvas(画布)是一个矩形区域,可以放置图形、图像、组件等。
实操代码:
import random
from tkinter import Frame, Canvas, PhotoImage, Button, Tk
class Application(Frame):
# 1. 初始化
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.createWidget()
def createWidget(self):
# 2. 组件相关
self.canvas = Canvas(self, width=300, height=200, bg="green")
self.canvas.pack()
# 画一条线
line = self.canvas.create_line(10, 10, 30, 20, 40, 50)
# 画矩形
reat = self.canvas.create_rectangle(50, 50, 100, 100)
# 画椭圆, 前后一对坐标为椭圆的边界矩形左上角和底部右下角
oval = self.canvas.create_oval(50, 50, 100, 100)
global photo
photo = PhotoImage(file="111.gif")
self.canvas.create_image(250, 250, image=photo)
Button(self, text="来画10个矩形", command=self.draw10rect).pack(side="left")
def draw10rect(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(root)
root.mainloop()
结果展示:
不同于之前的信徒, 大主教和大祭司实力更加强大, 而且被控制的程度更深. GSC事先进行了分工: 由导师GSC对付大主教, 而了不起对付大祭司. 而当面对真正的强者时, GSC才真正认真起来. 开启名为杀意波动的领域, 只见很大一片区域内, 包括了不起和大祭司所在的区域, 处在领域内的敌人行动明显变得迟缓, 并且眼神中的疯狂仿佛被压制了不少. 了不起赶紧抓住机会, 使用起最近学习到的突刺技能, 在奥菲利亚的增幅下, 命中领主. 大祭司受伤之后, 开始疯狂的召唤GBK教徒, 向其冲去. 然而在导师领域和奥菲利亚的增幅下, 不一会便将这些教徒击晕. 了不起毫不畏惧,步步为营. 近身战结合远程法术, 花费半天时间终于将其在丝血时击晕. 最后在奥菲利亚的净化魔法的帮助下, 大主教和大祭司都恢复了意识. 而他们脱口而出的第一句话, 便让了不起惊掉下巴...
之间他们苏醒之后, 脱口而出的第一句话便是: 伟大的教主大人, 请原谅我等所犯下的罪行...什么? 原来了不起拯救的红发少女是GBK的教主. 在他们三者沟通完毕后, 奥菲利亚也略显歉意地向了不起解释道, 由于之前得知阿拉德大陆上的人都比较奸诈的, 担心我们图谋不轨, 因此没说明其真正身份. 在帮助大祭司和大神官接触控制之后, 明白了我们的伟人, 于是说明情况并请求我们的原谅. 而了不起的心里也有震惊中慢慢恢复, 在原谅了她之后便回到GBK外围住所从长记忆...而了不起由于这两天参与的高强度战斗与大批量敌人的遭遇, 竟然从lv17升到了lv20.