Python GUI编程 | 10分钟轻松学会Tkinter

2021-08-09 14:54:08 浏览数 (1)

人生苦短,快学Python!

图形用户界面(GUI)是为用户交互提供灵活性的界面,很多小伙伴都希望把自己的Python小程序都加上一个可视化界面。即美观,又有交互性。常见的Python必备的GUI库有:Tkinter、PyQt5、Kivy、wxPython、PySimpleGUI等等。后续这些有用有趣的模块在快学Python都会陆续介绍的。

本篇文章将先结合实际案例,来介绍Tkinter的主要功能。

在案例开始之前,我们需要先认识一下 —— Tkinter

一、Tkinter初识

Tkinter,GUI编程的一个第三方库。是最受欢迎的软件包之一,它允许您使用 Python 构建 GUI!

而 GUI 即 graphicaluser interface,即图形界面用户接口,是相对于绝大多数编程语言所接触到的“控制台”的那个黑乎乎的命令行所区分的编程模式,Tkinter 是 Tk 的 Python 接口。

Tkinter 的优点和缺点

  1. 简单易学,相对于其他的比如 PyGtk,PyQt 等等,比较简单;
  2. 可以使用少量的代码产生功能强大的 GUI 界面,这一点是相对于 C 等语言来说的,这也是绝大多数脚本语言令人自豪的地方;
  3. 跨平台;
  4. 内置于Python 里面的,不需要我们单独去安装,是方便了很多,也是一个 Python 里面的标准;
  5. 缺点就是功能过于简单,使用tkinter这个框架提供的功能还是太少了,很多功能还是需要手动实现;
  6. 还有一个缺点是相对于 C 来说的,它的效率问题还是不算太高,对于一些对画面要求很高的。

二、第一个 tkinter 程序

起步

代码语言:javascript复制
import tkinter # 导入tkinter模块
tkinter._test() # 测试tkinter包是否好用

运行结果如下:

在这里点击quit按钮不会退出,只有点击X号才会退出程序。

第一个程序

代码语言:javascript复制
import tkinter
base = tkinter.Tk()  # Tk 这个类进行实例化,即 base 是它的一个实例
base.wm_title('Tk Test') # 设置标题
base.mainloop() # 进行事件循环

运行结果:

三、认识组件

如果大家习惯了 windows 编程,那么对于“控件”一次一定不会陌生,其实呢,组件和控件是一回事,在本书中我们不加以区分。

组件--Label

组件的英文表述是“widget”,我们常见的按钮,文本框等等都可以当做组件。我们可以为一个窗口增加若干组件来丰富该窗口的功能,我们往往需要指定这个组件的大小和位置,我们还需要通过编程的方式来指定该组件能完成什么功能。

Label标签

下面是代码示例:

代码语言:javascript复制
import tkinter

base = tkinter.Tk()  # 实例化

base.wm_title('Tk Test')

w1 = tkinter.Label(base,text='Python Label') # 创建一个label标签,放在base上

w1.pack()

base.mainloop()

运行结果:

代码解释:

1.这里的 Label 是一个类, 可以在__init__.py 文件里查看相应的源代码。 2.w1 是一个 Label 的实例, 它有一个 text 属性, 用来指定它的文本内容。 3.w1.pack() 表示布局,指定了摆放位置(后面会有详细提及)

  1. 多标签的应用程序

针对于多个标签的实例, 先声明,然后分别 pack 到窗口上即可。

下面是代码示例:

代码语言:javascript复制
from tkinter import *

root = Tk()

root.wm_title('组件')

w1 = Label(root,text='阿莱斯基的闪电',background='green')
w2 = Label(root,text='阿莱斯基的闪电',background='blue')
w3 = Label(root,text='阿莱斯基的闪电',background='yellow')

w1.pack()
w2.pack()
w3.pack()

root.mainloop()

运行结果:

组件--Button

按钮与功能的绑定

在按钮组件被声明的时候用 command 属性声明,command 属性接受一个函数名,注意函数名不要加双引号。

我们要完成的功能是我们按下这个按钮的时候,就会在窗口上增加一个背景颜色随机的 Label,它显示“我爱 python”。

代码语言:javascript复制
from tkinter import *
import random

color = ['red','orange','yellow','green','blue','purple','black']
def xinLovePython():
    global root
    b1 = Label(root,text='I like Python',background=random.choice(color))
    b1.pack()

root = Tk()
btn = Button(root,tetx = '九黎',command = xinLovePython)
btn.pack()

root.mainloop()

运行结果:

输入框

为了获取用户信息,很明显一直点击按钮不太合适,于是输入框出现了。

Entry(输入框)

  1. 部分源代码截图:
代码语言:javascript复制
class Entry(Widget, XView):
    def __init__(self, master=None, cnf={}, **kw):
        Widget.__init__(self, master, 'entry', cnf, kw)

    def get(self):
        """Return the text."""
        return self.tk.call(self._w, 'get')
  1. 源码中比较重要的函数是get 函数,get 函数使用的时候不需要任何参数,它的返回值就是该输入框的内容

密码框

  1. 其实密码框和输入框基本是一样的,都是向里面输入信息用的;
  2. 如果要说不一样, 也就一个地方不一样:密码框需要输入的信息的显示字符比较单一;
  3. 比如 e 是一个输入框,我们可以设置它的 show 属性让它变成一个密码框, 即 e[‘show’] = ‘*’就可以了。

代码示例:

代码语言:javascript复制
from tkinter import *

def login():
    s1 = e1.get()
    s2 = e2.get()
    t1= len(s1)
    t2 = len(s2)
    if s1 == 'yyds' and s2 == 'jiuli':
        c['text'] = '登录成功'

root = Tk() # 主界面
l = Label(root,text='用户名:') # 用户名的label
l.grid(row=0,column=0,sticky=W)

e1 = Entry(root)
e1.grid(row=0,column=1,sticky=E)

l2 = Label(root,text='密码:') # 密码的label
l2.grid(row=1,column=0,sticky=W)

e2 = Entry(root)
e2['show'] = '*'
e2.grid(row=1,column=1,sticky=E)

b = Button(root,text='登录',command=login)
b.grid(row=2,column=1,sticky=E)

c = Label(root,text='')
c.grid(row=3)
root.mainloop()

结果如下:

四、tkinter 的布局

常见的有三种布局方式:

pack布局

pack()布局非常简单, 我们不用做过多的设置, 直接使用一个pack 函数就可以了。

示例如下:

代码语言:javascript复制
from tkinter import *

baseFrame = Tk()

btn1 = Button(baseFrame,text='A',background='red').pack(side=LEFT,expand=YES,fill=Y)
btn2 = Button(baseFrame,text='B',background='blue').pack(side=TOP,expand=YES,fill=BOTH)
btn3 = Button(baseFrame,text='C',background='orange').pack(side=RIGHT,expand=YES,fill=None,anchor=NE)
btn4 = Button(baseFrame,text='D',background='yellow').pack(side=LEFT,expand=NO,fill=Y)
btn5 = Button(baseFrame,text='E',background='green').pack(side=TOP,expand=NO,fill=BOTH)
btn6 = Button(baseFrame,text='F',background='purple').pack(side=BOTTOM,expand=YES)
btn7 = Button(baseFrame,text='G',background='red').pack(anchor=SE)

baseFrame.mainloop()

运行结果:

解释:

我们使用 pack 函数的时候,默认先使用的放到上面,然后 依次向下排,它会给我们的组件一个自认为合适的位置和大小,这是默认方式,也是我们上面一直采用的方式。

pack 函数也可以接受几个参数:

  • side 参数指定了它停靠在哪个方向,可以为 LEFT,TOP,RIGHT,BOTTOM,分别代表左、上、右、下;
  • 它的 fill 参数可以是 X,Y,BOTH 和 NONE,即在水平方向填充、竖直方向填充、水平和竖直方向填充和不填充;
  • 它的 expand 参数可以是 YES 和 NO,它的 anchor 参数可以是 N,E,S,W(这里的 NESW 分别表示北东南西,这里分别 表示上右下左)以及他们的组合或者是 CENTER(表示中间);
  • 它的 ipadx 表示的是内边距的 x 方向,它的 ipady 表示的是内边距的 y 方向;
  • padx 表示的是外边距的 x 方向,pady 表示的是外边距的 y 方向;

grid布局

grid 可以理解为网格,或者表格,它可以把界面设置为几行几列的网格,我们在网格里插入我们想要的元素。

这种布局的好处是不管我们如何拖动窗口,相对位置是不会变化的,而且这种布局也超简单。

示例如下:

代码语言:javascript复制
from tkinter import *

xin = Tk()

# Entry 表示“输入框”。
Label(xin,text='账号:').grid(row=0,sticky= W)
Entry(xin).grid(row=0,column=1,sticky=E)

Label(xin,text='密码:').grid(row=1,sticky=W)
Entry(xin).grid(row=1,column=1,sticky=E)

Button(xin,text='登录:').grid(row=2,column=1,sticky=W)
xin.mainloop()

运行结果:

place布局

关于 place 布局,使用场景比较少;

它使用 place 函数,它分为绝对布局和相对布局、绝对布局使用 x 和 y 参数,相对布局使用 relx、rely,relheight 和 relwidth 参数。

五、事件

首先,什么是事件?

什么是事件?

  1. 事件的英文表述是“event”, 绝大多数界面编程也都会涉及到“事件”;
  2. 用户的很多操作,比如我们点击了一下鼠标, 这就是一个事件, 而操作系统会根据我们的相应的事件产生相应的 消息, 操作系统把消息传递给我们的应用程序, 然后我们的应用程序根据操作系统传入的数据执行相应的命令;
  3. 事件是用户触发的, 消息是操作系统根据而事件产生。

事件及其绑定

  1. 其实, 我们在按钮那一节就接触到了事件的绑定, 使用的函数是 bind;
  2. bind 函数的调用规则:窗体对象.bind(事件类型,回调函数)
  3. 所谓的“回调函数”, 就是这个函数我们不用去调用它, 当相应的事件发生的时候, 它会自动取调用。比如当我们 的按钮被按下的时候, 它会被自动调用。

常用的事件

  1. <Button-1> 表示鼠标左键单击,其中的 1 换成 3 表示右键被单击, 为 2 的时候表示鼠标中键, 感觉不算常用;
  2. <KeyPress-A> 表示 A 键被按下, 其中的 A 可以换成其他的键位;
  3. <Control-V> 表示按下的是 Ctrl 和 V 键, V 可以换成其他键位;
  4. <F1> 表示按下的是 F1 键, 对于 Fn 系列的, 都可以随便换。

绑定

  1. 事件不仅可以与 Button 绑定, 我们之前看过源代码, 发现 bind 函数是定义在 Misc 类里面的, 也就是说这个bind 可以被绝大多数组件类所使用;
  2. 我们可以让“标签”来模拟“按钮”的作用;
  3. 因为标签是 Label 类, 而 Label 类继承自 Widget, 而Widget 继承自 BaseWidget, 而 Basewidget 继承自 Misc;
  4. 其实不仅是标签可以模拟 button, 任何组件都可以模拟它, 只是那么有用。

标签模拟按钮

代码语言:javascript复制
from tkinter import *

root = Tk()

def Monibtn(event):
    global root
    mbtn = Label(root,text='测试')
    mbtn.pack()

l = Label(root,text='模拟按钮')
l.bind('<Button-1>',Monibtn)
l.pack()

root.mainloop()

如图所示:

bind 函数

关于 bind 函数,还有两种用法:

bind_all: 全程序级别的绑定, 它的参数类型和 bind 一样, 它通常用于全局的快捷键, 比如 F1 通常是用来打开帮助文档。

bind_class:绑定某些类别, 它接受三个参数, 第一个参数是类名, 第二个参数是事件类型, 第三个参数是相应的操作。

比如 w.bind_class(“Entry”,“<Control-V>”,my_paste), 它就是绑定了所有的所有的输入框的 Ctrl V 表示粘贴。

解除绑定

接触绑定我们使用 unbind 方法,它和 bind 的使用很相似;

不过 unbind 方法只需要一个参数就可以了, 它只需要解除绑定的事件类型, 因为它会解除该绑定事件类型的所有回调函数。

六、在线简单翻译程序

最后,我们使用一个案例(在线简单翻译程序),来实战一下Tkinter制作图形用户界面!

具体预期实现效果如下所示:

我们希望通过用户输入查询词,并获取然后向百度翻译发起请求得到结果,填充到结果框。

核心代码

数据请求

代码语言:javascript复制
def translate_word(string):
    url = "https://fanyi.baidu.com/sug"  # 请求数据的url链接
    data = {
     'kw':string,
    }
    data_url = urllib.parse.urlencode(data)
    req = urllib.request.Request(url=url,data=data_url.encode('utf-8'))
    response = urllib.request.urlopen(req).read()
    res = json.loads(response)
    return res['data'][0]['v'].split(';')[0]

使用urllib的方法去进行数据请求,得到json数据,转化为字典,由于翻译结果是有键值对,我们提取结果即可。

界面

代码语言:javascript复制
root = Tk()
root.title('小小翻译器')
root['width'] = 250;root['height'] = 130
Label(root,text='请输入要翻译的内容:',width=15).place(x=1,y=1)
Entry1 = Entry(root,width=20)
Entry1.place(x=110,y=1)
Label(root,text='翻译结果:',width=18).place(x=1,y=20)
s = StringVar()
s.set('')
Entry2 = Entry(root,width=20,textvariable=s)
Entry2.place(x=110,y=20)
Button1 = Button(root,text='翻译',width=8)
Button1.place(x=40,y=80)
Button2 = Button(root, text='清空', width=8)
Button2.place(x=130, y=80)
Button1.bind("<Button-1>",leftClick) # 事件绑定
Button2.bind("<Button-1>",leftClick2) # 事件绑定

如下所示:

函数绑定

翻译按钮函数绑定:

代码语言:javascript复制
def leftClick(evvnt):
    enstr = Entry1.get() # 获得翻译词的内容
    vText = translate_word(enstr) # 翻译函数得到翻译结果
    Entry2.config(Entry2,text=vText) # 翻译结果填充到第二个输入框
    s.set('')
    Entry2.insert(0,vText)

清空按钮函数绑定:

代码语言:javascript复制
def leftClick2():
     s.set('')
     Entry2.insert(0,'') # 清空译文内容

七、小结

Tkinter模块("Tk 接口")是Python的标准 Tk GUI工具包的接口。

Tkinter提供了大量组件进行图形界面开发,以创建功能复杂的界面程序,跨平台的特点是Tkinter的优势之一,可以在大多数的Unix平台下使用,同样可以应用在WindowsMacintosh系统里,通过与爬虫程序的结合,打造简单的GUI界面应用程序。

在后续的文章中,我们将继续介绍PyQt5、wxPython、PySimpleGUI等GUI库的使用方法!

人生苦短,快学Python

0 人点赞