python GUI图形界面化编程——Tkinter

一、前言

由于本篇文章较长,所以下面给出内容目录方便跳转阅读

一、GUI图形界面化编程

GUI 编程类似于“搭积木”,将一个个组件(Widget)放到 窗口中。如下是 windows 中的画图软件,就是一个典型的 GUI 程序:
在这里插入图片描述
上面的各种按钮、菜单、编辑区域等都是一个个组件,它 们都放置到窗口中,并通过增加“对事件的处理”成为一个 完整的程序。

二、常用的GUI库
  1. Tkinter
    tkinter(Tk interface)是 Python 的标准 GUI 库,支持跨平台的 GUI 程序开发。tkinter 适合小型的 GUI 程序编写,也特别适合初学者学习 GUI 编程。本博客以 tkinter 为核心进行讲解。
  2. wxPython
    wxPython是比较流行的GUI库,适合大型应用程序开发,功能强于 tkinter,整体设计框架类似于 MFC(Microsoft Foundation Classes 微软基础类库)。
  3. PyQT
    Qt 是一种开源的 GUI 库,适合大型 GUI 程序开发,PyQT是 Qt 工具包标准的 Python 实现。我们也可以使用 Qt Desginer 界面设计器快速开发 GUI 应用程序。
三、GUI 编程的核心步骤和第一个 GUI 程序

基于 tkinter 模块创建 GUI 程序包含如下 4 个核心步骤:

1. 创建应用程序主窗口对象(也称:根窗口),通过类 Tk 的无参构造函数

from tkinter import *
root = Tk()

2. 在主窗口中,添加各种可视化组件,比如:按钮(Button)、文本框(Label)等

btn01 = Button(root)
btn01["text"] = "这是一个按钮" 

3. 通过几何布局管理器,管理组件的大小和位置

btn01.pack()

4. 事件处理
通过绑定事件处理程序,响应用户操作所触发的事件(比如:单击、双击等)
def click(event):
    messagebox.showinfo("Message","按钮被点击了")
btn01.bind("<Button-1>",click)

【示例】使用 tkinter 模块,创建 GUI 应用程序,并实现点击按钮的事件处理

from tkinter import *
from tkinter import messagebox

root = Tk()
btn01 = Button(root)
btn01["text"] = "这是一个按钮" 
btn01.pack()

def click(event):
    messagebox.showinfo("Message","按钮被点击了")
btn01.bind("<Button-1>",click)
    
btn01.bind("<Button-1>",click)
root.mainloop() #调用组件的 mainloop 方法,进入事件循环
设置窗口的大小

初始化的窗口,是一个很小的窗口,连标题都无法正常显示。因此需要在程序开始的时候设置窗口的大小。
窗口有4个与大小有关的函数:

函数说明
winfo_screenwidth()整个屏幕宽度是电脑屏幕的宽度
winfo_screenheight()整个屏幕长度是电脑屏幕的长度
winfo_reqwidth()窗口宽度
winfo_reqheight()窗口长度

有了这4个函数,我们就可以轻松的实现窗口大小的调整与在屏幕中间显示。如果没有调整的话,我们创建的tkinter窗口出现在屏幕的位置,每次都是不同的。下面的程序就可以实现调整窗口大小,并在屏幕居中显示:

import tkinter  as tk
def center_window(root, width, height):
    screenwidth = root.winfo_screenwidth()
    screenheight = root.winfo_screenheight()
    size = '%dx%d+%d+%d' % (width, height, (screenwidth - width)/2, (screenheight - height)/2)
    root.geometry(size)
root = tk.Tk()
root.title('调整窗口大小')
center_window(root, 400, 320)
root.mainloop()
四、GUI编程整体描述

用户图形界面是由一个个组件组成,就像小孩“搭积木”一样最终组成了整个界面。有的组件还能在里面再放置其他组件,我们称为“容器”。Tkinter 的 GUI 组件关系图如下:
在这里插入图片描述

Misc 和 Wm: 
• Tkinter 的 GUI 组件有两个根父类,它们都直接继承了 object 类: 
• Misc:它是所有组件的根父类。 
• Wm:它主要提供了一些与窗口管理器通信的功能函数。

Tk 
• Misc 和 Wm 派生出子类 Tk,它代表应用程序的主窗口。一般应用程序都需要直接或间接使用 Tk。 

Pack、Place、Grid 
• Pack、Place、Grid 是布局管理器。布局管理器管理组件的:大小、位置。通过布局管 理器可以将容器中的组件实现合理的排布。
五、常用组件汇总列表

在这里插入图片描述

六、GUI 应用程序类的经典写法

本节程序也是 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) 
        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()
七、动手实践学习简单组件的使用
1、 Label标签部件
# 该程序并未对主窗口进行设置,对主窗口的设置会在后面提到

import tkinter as tk  # 使用Tkinter前需要先导入
 
# 第1步,建立主窗口window
window = tk.Tk()
 
# 第2步,在主窗口内部添加Label组件
l = tk.Label(window, text='this is Label', bg='green', width=30, height=2)
# 说明: bg为背景颜色,width为长,height为高,这里的长和高是字符的长和高,比如height=2,就是标签有2个字符这么高
 
# 第3步,放置标签
l.pack()    # Label内容content区域放置位置,自动调节尺寸
# 放置lable的方法有:1)l.pack(); 2)l.place(); 3)l.grid()
 
# 第4步,主窗口循环显示
window.mainloop()
# 注意,loop因为是循环的意思,window.mainloop就会让window不断的刷新,如果没有mainloop,就是一个静态的window,传入进去的值就不会有循环,mainloop就相当于一个很大的while循环,有个while,每点击一次就会更新一次,所以我们必须要有循环
# 所有的窗口文件都必须有类似的mainloop函数,mainloop是窗口文件的关键的关键
2、Button按钮部件

Button(按钮)部件是一个标准的Tkinter窗口部件,用来实现各种按钮。按钮能够包含文本或图象,并且你能够将按钮与一个Python函数或方法相关联。当这个按钮被按下时,Tkinter自动调用相关联的函数或方法。

# 在该程序中涉及到主窗口的设置,以及方法的绑定

import tkinter as tk  # 使用Tkinter前需要先导入
 
# 第1步,建立主窗口window
window = tk.Tk()
 
# 第2步,给窗口的可视化起名字
window.title('My Window')
 
# 第3步,设定窗口的大小(长 * 宽)
window.geometry('500x300')  # 这里的乘是小x
 
# 第4步,在图形界面上设定标签
var = tk.StringVar()    # 将label标签的内容设置为字符类型,用var来接收hit_me函数的传出内容用以显示在标签上
l = tk.Label(window, textvariable=var, bg='green', fg='white', font=('Arial', 12), width=30, height=2)
# 说明: bg为背景,fg为字体颜色,font为字体,width为长,height为高,这里的长和高是字符的长和高,比如height=2,就是标签有2个字符这么高
l.pack()
 
# 定义一个函数功能(内容自己自由编写),供点击Button按键时调用,调用命令参数command=函数名
def hit_me():
    if var.get() == '':
        var.set('you hit me')
    else:
         var.set('')
 
# 第5步,在窗口界面设置放置Button按键
b = tk.Button(window, text='hit me', font=('Arial', 12), width=10, height=1, command=hit_me)
b.pack()
 
# 第6步,主窗口循环显示
window.mainloop()
3、 Entry单行文本框部件

Entry是tkinter类中提供的的一个单行文本输入域,用来输入显示一行文本,收集键盘输入
在这里插入图片描述
【示例】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")

        # 创建密码框
        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=="admin" and pwd=="123456":
            messagebox.showinfo("登录系统", "登录成功!欢迎开始学习!")
        else:
            messagebox.showinfo("登录系统","登录失败!用户名或密码错误!")
            
            
if __name__ == '__main__':
    root = Tk()
    root.geometry("400x130+200+300")
    app = Application(master=root)
    root.mainloop()
4、Text多行文本框部件

Text是tkinter类中提供的的一个多行文本区域,显示多行文本,可用来收集(或显示)用户输入的文字

"""测试 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")
        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, ' Cheney ')
        # END 索引号表示在最后插入
        self.w1.insert(END, 'logic')
        self.w1.insert(1.8, "Cheney")
               
    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()

在这里插入图片描述

5、Radiobutton

单选按钮 Radiobutton 控件用于选择同一组单选按钮中的一个。 Radiobutton 可以显示文本,也可以显示图像。

"""测试 Radiobutton 组件的基本用法,使用面向对象的方式"""

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.v = StringVar();
        self.v.set("F")
        # 其中variable=self.v, value='M'的意思就是,当我们鼠标选中了其中一个选项,把value的值放到变量self.v中
        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()
6、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() 
八、Options选项详解

通过学习 以上组件,我们发现可以通过 Options 设置组件的属性,从而控制组件的各
种状态。比如:宽度、高度、颜色、位置等等

1. 创建对象时,使用可变参数
fred = Button(self, fg="red", bg="blue")

2. 创建对象后,使用字典索引方式
fred["fg"] = "red"
fred["bg"] = "blue"

3. 创建对象后,使用 config()方法
fred.config(fg="red", bg="blue")
如何查看组件的 Options 选项:
1. 可以通过打印 config()方法的返回值,查看 Options 选项
print(fred.config())

2. 通过在 IDE 中,点击组件对象的构造方法,进入到方法内观察:
我们可以看到如下的代码:
class Button(Widget):
    """Button widget."""
    def __init__(self, master=None, cnf={}, **kw):
        """Construct a button widget with the parent MASTER.
        STANDARD OPTIONS
            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-SPECIFIC OPTIONS
            command, compound, default, height,
            overrelief, state, width
        """
        Widget.__init__(self, master, 'button', cnf, kw)

我们将常见的选项汇总如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页