Python编写软件界面,打造出简洁易用的界面设计

大家好,本文将围绕python做出软件的界面展开说明,python编写的软件界面是一个很多人都想弄明白的事情,想搞清楚python应用程序界面需要先了解以下几个事情。

本篇文章给大家谈谈python如何做出图形界面,以及用python做图形用户界面,希望对各位有所帮助,不要忘了收藏本站喔。

一、图形界面编程

图形用户界面(Graphical User Interface,GUI)是用户与程序交互的接口,好的GUI会大大提高用户交互体验,其实就是我们平时使用电脑时,使用鼠标、键盘点击的程序界面python实现猴子跳台阶。
Python提供很多创建GUI的程序库,程序员可以选择其中的一个来创建自己的程序界面ai伪原创api,如何用php调用。

  • PyGObject: 基于GObject的C函数库提供了内省绑定,这些库支持GTK+3图形界面工具集,因此PyGObject提供了丰富的图形界面组件。
  • PyGTK:基于老版GTK+2的库(C语言)提供绑定,官方网站。
  • PyQt:Python编程语言和Qt库(C++GUI应用开放框架)的融合,可跨平台使用
  • PySide:Nokia提供的Qt封装,
  • wxPython:以wxWidgets为基础,在不同平台调用不同的本都组件,以符合平台风格。跨平台GUI库,官方网站。
  • 如果读者需要,可以选择任意的GUI库来开发图形界面。如果考虑开发跨平台界面,推荐使用PyQt或wxPython。
    本章介绍的GUI库时Tkinter,它是Python自带的GUI库,无需额外下载安装,只要导入tkinter包即可使用。
    与其他编程语言的 GUI 工具包相比,Tkinter 编码效率高,能够实现快速开发的目的,非常适合初学者学习。Tkinter 使用纯 Python 语言开发,与 C/C++ 开发的 Qt 框架相比,Tkinter 有自身的局限性,比如性能、功能丰富程度等都不及 Qt,因此它只适合开发一些简单的程序,比如计算器的界面,或者一个简易的聊天窗口等。
    学习GUI编程类似于搭建积木的过程,我们也通过这个步骤来讲解:

    1. 了解我们这套积木中都含有哪些积木块(GUI库中包含的组件),都是个什么东西。
    2. 准备一张桌子来作为工作场地(建立程序主窗口)
    3. 将积木拼接在一起(在容器/窗口中对组件布局)
    4. 深入掌握每个积木块的功能和用法(各组件用法,完成工作内容)
      接下来我们将一步一步实现界面编程。

    1.1 Tkinter GUI编程组件

    其实,Tkinter是一个程序包,里面包含了很多模块,例如Tk、ttk、messagebox等,Tk模块是创建简单界面的主要模块,其中的组件也是继承了object类,下图显示了各组件的继承关系:

    现在我们来了解一下‘积木块’的大体功能,不求完全记住,后面还会有详细讲解。
    下表列出了 Tkinter 中常用的 15 个组件:

    组件类型 组件名称 组件作用
    Button 按钮 点击按钮时触发/执行一些事件(函数)
    Canvas 画布 提供绘制图,比如直线、矩形、多边形等
    Checkbutton 复选框 多项选择按钮,用于在程序中提供多项选择框
    Entry 文本框输入框 用于接收单行文本输入
    Frame 框架(容器)控件 定义一个窗体(根窗口也是一个窗体),用于承载其他控件,即作为其他控件的容器
    Lable 标签控件 用于显示单行文本或者图片
    LableFrame 容器控件 一个简单的容器控件,常用于复杂的窗口布局。
    Listbox 列表框控件 以列表的形式显示文本
    Menu 菜单控件 菜单组件(下拉菜单和弹出菜单)
    Menubutton 菜单按钮控件 用于显示菜单项
    Message 信息控件 用于显示多行不可编辑的文本,与 Label控件类似,增加了自动分行的功能
    messageBox 消息框控件 定义与用户交互的消息对话框
    OptionMenu 选项菜单 下拉菜单
    PanedWindow 窗口布局管理组件 为组件提供一个框架,允许用户自己划分窗口空间
    Radiobutton 单选框 单项选择按钮,只允许从多个选项中选择一项
    Scale 进度条控件 定义一个线性“滑块”用来控制范围,可以设定起始值和结束值,并显示当前位置的精确值
    Spinbox 高级输入框 Entry 控件的升级版,可以通过该组件的上、下箭头选择不同的值
    Scrollbar 滚动条 默认垂直方向,鼠标拖动改变数值,可以和 Text、Listbox、Canvas等控件配合使用
    Text 多行文本框 接收或输出多行文本内容
    Toplevel 子窗口 在创建一个独立于主窗口之外的子窗口,位于主窗口的上一层,可作为其他控件的容器

    在后续内容中,我们会陆续对上表中涉及的组件(也有称为控件的)进行介绍。当然,除了上述组件外,还有一些高级组件,比如 PanedWindow、messagebox、LableFrame、Spinbox,在后续章节也会讲解。
    从上表来看,每个组件都有着各自不同的功能,即使有些组件功能相似,但它们的适用场景也不同。

    在 Tkinter 中不同的组件受到各自参数的约束(即参数),所有组件既有相同属性,也有各自独有的属性。本节内容,先对这些组件的共用属性做简单介绍,如下表所示:

    属性名称 说明 单位 典型值
    background(bg) 背景颜色,参数值可以颜色的十六进制数,或者颜色英文单词 COLOR ‘gray25’或‘#ff4400’
    foreground(fg) 前景色,也就是字体的颜色,参数值可以颜色的十六进制数,或者颜色英文单词 COLOR ‘gray25’或‘#ff4400’
    activebackground 激活状态时的背景色 color ‘gray25’或‘#ff4400’
    activeforeground 激活状态时的前景色 color ‘gray25’或‘#ff4400’
    highlightbackground 高亮状态时的背景色 color ‘gray25’或‘#ff4400’
    highlightcolor 高亮状态时的前景色 color ‘gray25’或‘#ff4400’
    selectbackground 选中状态时的背景色 color ‘gray25’或‘#ff4400’
    selecforeground 选中状态时的前景色 color ‘gray25’或‘#ff4400’
    disabledforground 禁止状态时的前景色 color ‘gray25’或‘#ff4400’
    height 该参数值用来设置组件的高度,文本控件以字符的高度(px,font指定),其他控件则以像素为单位 px或pixel 14
    width 用于设置控件的宽度,文本控件以字符的高度(px,font指定),其他控件则以像素为单位 px或pixel 14
    borderwidth 定于组件的边框宽度 pixel 2
    highlightthickness 高亮状态下周围方形区域宽度 pixel 2
    selectborderwidth 选中状态时的边框宽度 pixel 2
    relief 定义组件的边框样式 constant FLAT(平的)/RAISED(凸起的)/SUNKEN(凹陷的)/GROOVE(沟槽桩边缘)/RIDGE(脊状边缘)
    image 定义显示在组件内的图片文件 address
    bitmap 定义显示在组件内的位图文件,受anchor、justify选项影响,同时指定bitmap、text、image时,可能会覆盖低优先级的选项,优先级关系为image>bitmap>text address
    text 定义控件的标题文字 str ‘确定’
    testcariable 指定显示文本的变量 variable bnText
    font 若组件支持设置标题文字,就可以使用此属性来定义,它是一个数组格式的参数 (字体,大小,字体样式) 数组 ‘Helvetica’或(‘Verdana’,8)
    anchor 定义组件信息(文本或图片)在窗口内的位置 N(上)、NE(左上角)、E(右)、SE、S、SW、W、NW、CENTER
    justify 定义多行文字的对齐方式 constant LEFT/CENTER/RIGHT
    padx/pady 定义组件内的文字或者图片与控件边框之间的水平/垂直距离 pixel 12
    state 控制组件是否处于可用状态 constant 参数值默认为 NORMAL/DISABLED,默认为 NORMAL(正常的)
    takefocus 组件在键盘遍历(Tab或Shift+Tab)时,是否接收焦点 boolean 1或Yes(接受);0或No(不接收)
    command 执行事件函数,比如单击按钮时执行特定的动作,可将执行用户自定义的函数
    cursor 当鼠标指针移动到组件上时,定义鼠标指针的类型 cursor crosshair(十字光标)、watch(待加载圆圈)、plus(加号)、arrow(箭头)、gumby等
    注意:对于上述属性先做大体的了解即可,因为后续章节会对这些控件做更为详细的介绍。

    1.2 建立主窗口Tk

    主窗口(Tk对象)是一切组件的基础,它好比是一台高速运转的机器,而其他控件则相当于这台机器上的部件,比如齿轮、链条、螺丝等等。由此我们知道,主窗口是一切控件的基础,所有的控件的都需要通过主窗口来显示。
    Tkinter 能够很方便地创建一个空白窗口,值得注意的是Python 2.x需要import Tkinter,Python 3.x需要import tkinter。
    创建窗口对象可以使用2中方法,

    1. 使用Tk()类创建窗口(此时里面什么都没有,指定了自命名的master主窗口)
    2. 直接创建组件的子类,可以默认初始化一个含有该组件的窗口(使用self.master引用),不建议这么使用。
    1.2.1 使用Tk()创建窗口

    示例代码如下:

    # 导入tk
    from tkinter import *
    # 创建一个主窗口对象
    window = Tk()
    # 调用mainloop()显示主窗口
    window.mainloop()
    

    程序运行结果如下:

    1. 窗口常用方法
      下表列出了窗口的常用方法,其中 window 代表主窗口对象:
    函数 说明
    window.title(“my title”) 接受一个字符串参数,为窗口起一个标题
    window.resizable() 是否允许用户拉伸主窗口大小,默认为可更改,当设置为 resizable(0,0)或者resizable(False,False)时不可更改
    window.geometry() 设定主窗口的大小以及位置,当参数值为 None 时表示获取窗口的大小和位置信息。
    window.quit() 关闭当前窗口
    window.update() 刷新当前窗口
    window.mainloop() 设置窗口主循环,使窗口循环显示(一直显示,指导窗口被关闭)
    window.iconbitmap() 设置窗口左上角的图标(图标是.ico文件类型)
    window.config(background =“red”) 设置窗口的背景色为红色,也可以接受 16 进制的颜色值
    window.minsize(50,50) 设置窗口被允许调整的最小范围,即宽和高各50
    window.maxsize(400,400) 设置窗口被允许调整的最大范围,即宽和高各400
    window.attributes(“-alpha”,0.5) 用来设置窗口的一些属性,比如透明度(-alpha)、是否置顶(-topmost)即将主屏置于其他图标之上、是否全屏(-fullscreen)全屏显示等
    window.state(“normal”) 用来设置窗口的显示状态,参数值 normal(正常显示),icon(最小化),zoomed(最大化)
    window.withdraw() 用来隐藏主窗口,但不会销毁窗口。
    window.iconify() 设置窗口最小化
    window.deiconify() 将窗口从隐藏状态还原
    window.winfo_screenwidth() 获取电脑屏幕的分辨率(尺寸)
    window.winfo_screenheight() 获取电脑屏幕的分辨率(尺寸)
    window.winfo_width()
    window.winfo_height() 获取窗口的大小,同样也适用于其他控件,但是使用前需要使用 window.update() 刷新屏幕,否则返回值为1
    window.protocol(“协议名”,回调函数) 启用协议处理机制,常用协议有 WN_DELETE_WINDOW,当用户点击关闭窗口时,窗口不会关闭,而是触发回调函数。

    下面通一个示例对上述表格中的常用方法做简单地介绍:

    import tkinter as tk
    window =tk.Tk()
    #设置窗口title
    window.title('Python学习')
    #设置窗口大小:宽x高,注,此处不能为 "*",必须使用 "x"
    window.geometry('450x300')
    # 获取电脑屏幕的大小
    print("电脑的分辨率是%dx%d"%(window.winfo_screenwidth(),window.winfo_screenheight()))
    # 要求窗口的大小,必须先刷新一下屏幕
    window.update()
    print("窗口的分辨率是%dx%d"%(window.winfo_width(),window.winfo_height()))
    # 如使用该函数则窗口不能被拉伸
    # window.resizable(0,0)
    # 改变背景颜色
    window.config(background="#6fb765")
    # 设置窗口处于顶层
    window.attributes('-topmost',True)
    # 设置窗口的透明度
    window.attributes('-alpha',1)
    # 设置窗口被允许最大调整的范围,与resizble()冲突
    window.maxsize(600,600)
    # 设置窗口被允许最小调整的范围,与resizble()冲突
    window.minsize(50,50)
    #更改左上角窗口的的icon图标,加载C语言中文网logo标
    window.iconbitmap('C:/Users/Administrator/Desktop/favicon.ico')
    #添加文本内容,并对字体添加相应的格式 font(字体,字号,"字体类型")
    text=tk.Label(window,text="Python学习,网址:https://editor.csdn.net",bg="yellow",fg="red",font=('Times', 15, 'bold italic underline'))
    #将文本内容放置在主窗口内
    text.pack()
    # 添加按钮,以及按钮的文本,并通过command 参数设置关闭窗口的功能
    button=tk.Button(window,text="关闭",command=window.quit)
    # 将按钮放置在主窗口内
    button.pack(side="bottom")
    #进入主循环,显示主窗口
    window.mainloop()
    
    1. protocol协议处理机制
      Tkinter 除了提供事件绑定机制之外,还提供了协议处理机制,它指的是应用程序和窗口管理器之间的交互,最常用的协议为 WM_DELETE_WINDOW。

    当 Tkinter 使用 WM_DELETE_WINDOW 协议与主窗口进行交互时,Tkinter 主窗口右上角x号的关闭功能失效,也就是无法通过点击x来关闭窗口,而是转变成调用用户自定义的函数。

    下面看一组简单的示例:

    from tkinter import Tk
    # 导入 对话框控件
    from tkinter import messagebox
    # 创建主窗口
    root = Tk()
    # 定义回调函数,当用户点击窗口x退出时,执行用户自定义的函数
    def QueryWindow():
        # 显示一个警告信息,点击确后,销毁窗口
        if messagebox.showwarning("警告","出现了一个错误"):
            # 这里必须使用 destory()关闭窗口
            root.destroy()
    # 使用协议机制与窗口交互,并回调用户自定义的函数
    root.protocol('WM_DELETE_WINDOW', QueryWindow)
    root.mainloop()
    

    通过封装函数的形式来执行相应的 GUI 控件功能,这在学习 Tkinter 编程的整个过程中非常常见,比如 Button 控件的command参数也可以执行回调函数,如下所示:

    import tkinter as tk
    # 定义窗口
    window = tk.Tk()
    window.title('Python学习')
    window.geometry('300x300')
    window.iconbitmap('C:/Users/Administrator/Desktop/favicon.ico')
    # 定义回调函数
    def callback():
        print("执行回调函数","欢迎学习Python")
    # 点击执行按钮
    button = tk.Button(window, text="执行", command=callback)
    button.pack()
    window.mainloop()
    

    设置窗口位置
    当我们运行 Tkinter 程序时,主窗口都会出现在距离屏幕左上角指定的位置上,这是由 Tkinter 软件包默认设置的。但是在许多情况下,我们需要根据实际情况来移动窗口在电脑屏幕上的位置,这时应该如何处理呢?其实很简单,通过窗口对象的 geometry() 方法即可改变主窗口的位置,其语法格式如下:

    geometry('450x400+300+200')
    

    上述代码表示,设置主窗口的宽度为 450,高度为 400,同时窗口距离左边屏幕的距离为 300(以像素为单位),距离屏幕顶部的距离为 200,这里我们将带“+”的参数值称为“位置参数”,当然,您也可以将它们设置为负数,如下所示:

    geometry('+-1500+-2000')
    

    当设置了一个超过屏幕的负参数值时,主窗口会被移动至“屏幕之外”,此时就看不到主窗口了,这也是隐藏窗口的一种方法。

    下面看一组简单的示例:

    import tkinter as tk
    window = tk.Tk()
    window.title('Python学习')
    window.iconbitmap('C:/Users/Administrator/Desktop/favicon.ico')
    # 设置窗口大小变量
    width = 300
    height = 300
    # 窗口居中,获取屏幕尺寸以计算布局参数,使窗口居屏幕中央
    screenwidth = window.winfo_screenwidth()
    screenheight = window.winfo_screenheight()
    size_geo = '%dx%d+%d+%d' % (width, height, (screenwidth-width)/2, (screenheight-height)/2)
    window.geometry(size_geo)
    window.mainloop()
    

    程序运行后窗口将出现在屏幕的中间位置。

    1.2.2 使用组件创建窗口

    上一小节我们使用TK()创建了主窗口,然后在Windows主窗口上面创建组件的方式来构建我们的用户接口。还有一种方式就是字节创建组件的子类,子类就会自动创建TK对象作为窗口,例如下面的程序(以Frame为例)

    from thinter import *
    #定义继承Frame的Application类
    class Application(Frame):
        def __init__(self,master=None):
            Frame.__init__(self,master)
            self.pack()
            # 调用initWidgets()方法初始化界面
            self.initWidgets()
        def initWidgets(self):
            #创建Lable对象,第一个参数指定将该Lable放入本类(self)中
            w = Lable(self)
            #创建一个位图
            bm = PhotoImage(file = 'serial.png')
            #使用一个变量引用图片,避免图片变量无引用时被自动回收
            w.x = bm
            #设置Lable显示图片
            w['image'] = bm
            #放入窗口中
            w.pack()
            # 创建Button对象
            okButton = Button(self,text='确定‘)
            okButton['background'] = 'yellow'
            # okButton.configure(background='yellow') # 与上面代码作用相同
            okButton.pack()
            #创建Application对象
            app = Application()
            #组件的master属性值是Tk对象(窗口)
            print(type(app.master))
            # 通过master属性来设置窗口属性
            app.master.title('窗口标题’)
            # 启动主窗口消息循环
            app.mainloop()
            
    

    本例直接使用子类创建了组件,并没有直接指定master属性,而是使用了系统自动生成的主窗口。
    另外需要学习的内容是组件怎么在窗口中工作的:

  • 创建GUI组件,相当于创建‘积木块’,指定组件属于哪个容器(主窗口,本例使用self,未指定master),
  • 添加GUI组件,此处使用了pack()方法将组件添加到主窗口中
  • 配置GUI组件,实质就是为组件的属性赋值,例如title = ‘窗口标题’
  • 通常配置组件有两个时机:

  • 创建组件时,以关键字方式配置,例如Button(self,text='确定‘)
  • 创建完成后,以字典语法配置,例如okButton[‘background’]=‘yellow’
  • 需要注意的是,每种组件有自己的配置选项,前面我们介绍了组件的一些通用的、常用的属性,特殊属性可以使用帮助文档学习,本处不在介绍,

    1.3 组件布局

    前面我们介绍了’积木块‘(组件),’拼装桌面‘(主窗口Tk对象),接下来要做的就是将这些组件怎么拼接在一起,也就是积木的组装过程。
    一个优秀的图形用户界面,更像是艺术家的作品,它会给用户非常良好的感官体验,因此布局管理不单单是枯燥的程序代码,更需要以“美”的角度去审视每一个细节,这才是学习布局管理的“不二法门”。Tkinter 提供了一系列布局管理的方法和容器控件,通过对这些内容的学习,您将掌握如何使用不同的方法完成界面布局。

    1.3.1 布局管理器

    Tkinter 提供了三种常用的布局管理器,分别是 pack()、grid() 以及 place(),如下表所示:

    方法 说明
    pack() 按照控件的添加顺序其进行排列,遗憾的是此方法灵活性较差
    grid() 以行和列(网格)形式对控件进行排列,此种方法使用起来较为灵活
    place() 可以指定组件大小以及摆放位置,三个方法中最为灵活的布局方法

    上述三种方法适用于 Tkinter 中的所有控件,在讲解前面内容时,对其中一些方法已经做了相关的介绍。在本节会对上述三个方法的应用场景做更为详细的介绍。

    1.3.1.1 pack()布局

    pack() 是一种较为简单的布局方法,在不使用任何参数的情况下,它会将控件以添加时的先后顺序,自上而下,一行一行的进行排列,并且默认居中显示。pack() 方法的常用参数如下所示:

    属性 说明
    anchor 组件在窗口中的对齐方式,有 9 个方位参数值,比如"n"/“w”/“s”/“e”/“ne”,以及 “center” 等(这里的 e w s n分别代表,东西南北)
    expand 是否可扩展窗口,参数值为 True(扩展)或者 False(不扩展),默认为 False,若设置为 True,则组件的位置始终位于窗口的中央位置
    fill 参数值为 X/Y/BOTH/NONE,表示允许控件在水平/垂直/同时在两个方向上进行拉伸,比如当 fill = X 时,控件会占满水平方向上的所有剩余的空间。
    ipadx,ipady 需要与 fill 参数值共同使用,表示组件的内容和组件边框的距离(内边距),比如文本内容和组件边框的距离,单位为像素§,或者厘米©、英寸(i)
    padx,pady 用于控制组件之间的上下、左右的距离(外边距),单位为像素§,或者厘米©、英寸(i)
    side 组件放置在窗口的哪个位置上,参数值 ‘top’,‘bottom’,‘left’,‘right’。注意,单词小写时需要使用字符串格式,若为大写单词则不必使用字符串格式

    下面看一组简单的使用示例:

    from tkinter import  *
    win = Tk()
    win.title("Python学习")
    win.geometry('450x300+300+300')
    win.iconbitmap('C:/Users/Administrator/Desktop/logo.ico')
    lb_red = Label(win,text="红色",bg="Red",fg='#ffffff',relief=GROOVE)
    # 默认以top方式放置
    lb_red.pack()
    lb_blue = Label(win,text="蓝色",bg="blue",fg='#ffffff',relief=GROOVE)
    # 沿着水平方向填充,使用 pady 控制蓝色标签与其他标签的上下距离为 5 个像素
    lb_blue.pack(fill=X,pady='5px')
    lb_green = Label(win,text="绿色",bg="green",fg='#ffffff',relief=RAISED)
    # 将 黄色标签所在区域都填充为黄色,当使用 fill 参数时,必须设置 expand = 1,否则不能生效
    lb_green.pack(side=LEFT,expand=1,fill = BOTH)
    win.mainloop()
    
    1.3.1.2 grid()布局

    grid() 函数是一种基于网格式的布局管理方法,相当于把窗口看成了一张由行和列组成的表格。当使用该 grid 函数进行布局的时,表格内的每个单元格都可以放置一个控件。,从而实现对界面的布局管理。
    注意:这里的所说的“表格”是虚拟出来,目的是便于大家理解,其实窗体并不会因为使用了 gird() 函数,而增加一个表格。

    grid() 函数的常用参数如下所示:

    属性 说明
    column 控件位于表格中的第几列,窗体最左边的为起始列,默认为第 0 列
    columnsapn 控件实例所跨的列数,默认为 1 列,通过该参数可以合并一行中多个领近单元格。
    ipadx,ipady 用于控制内边距,在单元格内部,左右、上下方向上填充指定大小的空间。
    padx,pady 用于控制外边距,在单元格外部,左右、上下方向上填充指定大小的空间。
    row 控件位于表格中的第几行,窗体最上面为起始行,默认为第 0 行
    rowspan 控件实例所跨的行数,默认为 1 行,通过该参数可以合并一列中多个领近单元格。
    sticky 该属性用来设置控件位于单元格那个方位上,参数值和 anchor 相同,若不设置该参数则控件在单元格内居中

    grid() 方法相比 pack() 方法来说要更加灵活,以网格的方式对组件进行布局管理,让整个布局显得非常简洁、优雅。如果说非要从三个布局管理器中选择一个使用的话,那么我推荐大家使用 grid() 方法。
    这里有一点需要大家要特别注意,在一个程序中不能同时使用 pack() 和 grid() 方法,这两个方法只能二选一,否则程序会运行错误。
    下面看一组有关 grid() 函数的简单的示例:

    from tkinter import *
    #主窗口
    win = Tk()
    win.config(bg='#87CEEB')
    win.title("Python学习")
    win.geometry('500x350+300+300')
    win.iconbitmap('C:/Users/Administrator/Desktop/logo.ico')
    #在窗口内创建按钮,以表格的形式依次排列
    for i in range (10):
        for j in range (10):
            Button (win, text=" (" + str(i) + ","+ str(j)+ ")",bg='#D1EEEE') .grid(row=i,column=j)
    # 在第5行第11列添加一个Label标签
    Label(win,text="Python学习",fg='blue',font=('楷体',12,'bold')).grid(row =4,column=11)
    #开始窗口的事件循环
    win. mainloop()
    

    当使用 grid 函数布局的时,其实就是为各个控件指定行号、列号的过程,我们不需要为每个单元格指定大小,因为 grid 会为每个单元格自动设置一个适合的尺寸。

    下面通过 grid() 布局管理器制作一个简易的登录界面,代码如下所示:

    import tkinter as tk
    from tkinter import messagebox
    root = tk.Tk()
    root.title("Python学习")
    root.iconbitmap('C:/Users/Administrator/Desktop/logo.ico')
    root.resizable(0,0)
    tk.Label(root, text="用户名").grid(row=0, sticky="w")
    tk.Label(root, text="密码").grid(row=1, sticky="w")
    tk.Entry(root).grid(row=0, column=1)
    tk.Entry(root, show="*").grid(row=1, column=1)
    # 加载图片LOGO,注意这里是gif格式的图片
    photo = tk.PhotoImage(file="C:/Users/Administrator/Desktop/1.gif")
    tk.Label(root, image=photo).grid(row=0, column=2, rowspan=2, padx='4px', pady='5px')
    # 编写一个简单的回调函数
    def login():
        messagebox.showinfo('欢迎学习Python')
    # 使用grid()函数来布局,并控制按钮的显示位置
    tk.Button(root, text="登录", width=10, command=login).grid(row=3, column=0, columnspan=2,sticky="w", padx=10, pady=5)
    tk.Button(root, text="退出", width=10, command=root.quit).grid(row=3, column=1, columnspan=2,sticky="e", padx=10, pady=5)
    # 开启事件主循环
    root.mainloop()
    
    1.3.1.3 place()

    与前两种布局方法相比,采用 place() 方法进行布局管理要更加精细化,通过 place() 布局管理器可以直接指定控件在窗体内的绝对位置,或者相对于其他控件定位的相对位置。

    下面对 place 布局管理器的常用属性做相关介绍:

    属性 说明
    anchor 定义控件在窗体内的方位,参数值N/NE/E/SE/S/SW/W/NW 或 CENTER,默认值是 NW
    bordermode 定义控件的坐标是否要考虑边界的宽度,参数值为 OUTSIDE(排除边界) 或 INSIDE(包含边界),默认值 INSIDE。
    x、y 定义控件在根窗体中水平和垂直方向上的起始绝对位置
    relx、rely 定义控件相对于根窗口(或其他控件)在水平和垂直方向上的相对位置(即位移比例),取值范围再 0.0~1.0 之间; 可设置 in_ 参数项,相对于某个其他控件的位置
    height、width 控件自身的高度和宽度(单位为像素)
    relheight、relwidth 控件高度和宽度相对于根窗体高度和宽度的比例,取值也在 0.0~1.0 之间

    通过上述描述我们知道,relx和rely参数指定的是控件相对于父组件的位置,而relwidth和relheight参数则是指定控件相对于父组件的尺寸大小。
    注意:这里父组件指的是当前可操作控件的上层组件,比如在没有使用容器控件(frame)的窗体中,控件的父组件就是主窗口本身。
    上述表格中关于距离位置的参数容易产生“疑惑”,下面通过一组简单的示例来进一步说明:

    from tkinter import *
    #主窗口
    win = Tk()
    win.title("Python学习")
    win.iconbitmap('C:/Users/Administrator/Desktop/logo.ico')
    #创建一个frame窗体对象,用来包裹标签
    frame = Frame (win, relief=SUNKEN, borderwidth=2, width=450, height=250)
    # 在水平、垂直方向上填充窗体
    frame. pack (side=TOP, fill=BOTH, expand=1)
    # 创建 "位置1"
    Label1 = Label ( frame, text="位置1",bg='blue',fg='white')
    # 使用 place,设置第一个标签位于距离窗体左上角的位置(40,40)和其大小(width,height)
    # 注意这里(x,y)位置坐标指的是标签左上角的位置(以NW左上角进行绝对定位,默认为NW)
    Label1.place (x=40,y=40, width=60, height=30)
    # 设置标签2
    Label2 = Label (frame, text="位置2",bg='purple',fg='white')
    # 以右上角进行绝对值定位,anchor=NE,第二个标签的位置在距离窗体左上角的(180,80)
    Label2.place(x=180,y=80, anchor=NE, width=60, height=30)
    # 设置标签3
    Label3 = Label (frame, text="位置3",bg='green',fg='white')
    # 设置水平起始位置相对于窗体水平距离的0.6倍,垂直的绝对距离为80,大小为60,30
    Label3.place(relx=0.6,y=80, width=60, height=30)
    # 设置标签4
    Label4 = Label (frame, text="位置4",bg='gray',fg='white')
    # 设置水平起始位置相对于窗体水平距离的0.01倍,垂直的绝对距离为80,并设置高度为窗体高度比例的0.4倍,宽度为80
    Label4.place(relx=0.01,y=80,relheight=0.4,width=80)
    #开始事件循环
    win. mainloop()
    

    注意:在一个父组件中 place()方法可以与 grid() 方法混合使用,要与 pack() 进行区别。

    1.3.2 布局管理组件

    除了上一节《Tkinter布局管理方法》中提到的三个常用方法外,Tkinter 还提供了几个常用的布局管理控件,比如 Frame 、LabelFrame 等,这些控件的主要作用是为其他控件提供载体,并将主窗口界面划分成多个区域,从而方便开发者对不同区域进行设计与管理。

    在前文讲解其他的 Tkinter 控件时,我们列举的大多数示例都是将控件直接放置在主窗口(即根窗口)内,这样做的目的是为了便于大家理解。但在实际的开发过程中,控件一般放置在容器中,比如 Frame 容器控件,如同 HTML 中的

    标签一样,把容器看做成一个框架,其他控件则是这个框架中的“元素”。

    本节介绍了四种常用的容器控件以及它们的使用方法,分别是 Frame、LabelFrame、PanedWindow 以及 Toplevel。

    1.3.2.1 Frame控件

    Frame 本质上也是一个矩形窗体,同其他控件一样也需要位于主窗口内。我们可以在主窗口内放置多个 Frame 控件,并且每个 Frame 中还可以嵌套一个或者多个Frame,从而将主窗口界面划分成多个区域。

    Frame 控件的常用属性如下表所示:

    属性 说明
    bg 设置 Frame 的背景颜色
    bd 指定 Frame 的边框宽度
    colormap 指定 Frame 组件及其子组件的颜色映射
    container 布尔值参数,若参数值为 True,则窗体将被用作容器使用,一些其他程序也可以被嵌入。
    cursor 指定鼠标在 Frame 上飘过的鼠标样式,默认由系统指定
    height/width 设置 Frame 的高度和宽度
    highlightbackground 指定当 Frame 没有获得焦点的时候高亮边框的颜色,通常由系统指定为标准颜色
    highlightcolor 指定当 Frame 获得焦点的时候高亮边框的颜色
    highlightthickness 指定高亮边框的宽度,默认值是 0
    padx/pady 距离主窗口在水平/垂直方向上的外边距
    relief 指定边框的样式,参数值 “sunken”,“raised”,“groove” 或 “ridge”,“flat”,默认为 "falt’
    takefocus 布尔值参数,默认为 False,指定该组件是否接受输入焦点(即用户通过 Tab 键将焦点转移上来)

    下面看一组简单的示例,通过 Frame 将主窗口分成左右两个部分,如下所示:

    import tkinter as tk
    win = tk.Tk()
    win.title("Python学习")
    win.geometry('400x350+200+200')
    win.iconbitmap('C:/Users/Administrator/Desktop/logo.ico')
    # 在主窗口上添加一个frame控件
    frame1 = tk.Frame(win)
    frame1.pack()
    # 在frame_1上添加另外两个frame, 一个在靠左,一个靠右
    #左侧的frame
    frame_left = tk.Frame(frame1)
    tk.Label(frame_left,text='左侧标签1',bg='green',width=10,height=5).grid(row =0,column=0)
    tk.Label(frame_left,text='左侧标签2',bg='blue',width=10,height=5).grid(row = 1 ,column =1)
    frame_left.pack(side=tk.LEFT)
    frame_right = tk.Frame(frame1)
    tk.Label(frame_right,text='右侧标签1',bg='gray',width=10,height=5).grid(row = 0 ,column =1)
    tk.Label(frame_right,text='右侧标签2',bg='pink',width=10,height=5).grid(row = 1 ,column =0)
    tk.Label(frame_right,text='右侧标签3',bg='purple',width=10,height=5).grid(row= 1,column=1)
    frame_right.pack(side=tk.RIGHT)
    win.mainloop()
    

    上述示例利用 Frame 控件将主窗口分成了左右两个子区域,同时在各自区域中添加了 Label 标签,而且区域之间互不干扰。采用这种分区、分块的布局方式,可以使得 GUI 程序更加规范、简洁化。

    1.3.2.2 LabelFrame控件

    LabelFrame 控件也是一种容器类型的控件,它属于是 Frame 控件的变体,因此它们的属性选项大体相同。

    在默认情况下,LabelFrame 会在其包裹的子组件周围绘制一个边框和一个标题。当我们想要将一些相关的组件分为一组时,就可以使用 LabelFrame 组件,比如把一系列 Radiobutton(单选按钮)放在一起来供用户选择。

    同 Frame 控件一样,LabelFrame 的主要作用也是对控件进行分组处理,下面看一个具体的实例:

    import tkinter as tk
    win = tk.Tk()
    win.title("Python学习")
    win.geometry('800x350+200+200')
    win.iconbitmap('C:/Users/Administrator/Desktop/logo.ico')
    # 定义第一个容器,使用 labelanchor ='w' 来设置标题的方位
    frame_left = tk.LabelFrame(win, text="教程", labelanchor="w",bg='#5CACEE')
    # 使用 place 控制 LabelFrame 的位置
    frame_left.place(relx=0.2, rely=0.2, relwidth=0.2, relheight=0.5)
    label_1 = tk.Label(frame_left, text="C语言")
    label_1.place(relx=0.2, rely=0.2)
    label_2 = tk.Label(frame_left, text="Python")
    label_2.place(relx=0.6, rely=0.2)
    label_3 = tk.Label(frame_left, text="Java")
    label_3.place(relx=0.2, rely=0.6)
    label_4 = tk.Label(frame_left, text="C++")
    label_4.place(relx=0.6, rely=0.6)
    # 定义第二个容器,使用 labelanchor ='w' 来设置标题的方位
    frame_right = tk.LabelFrame(win, text="辅导班", labelanchor="w",bg='#66CDAA')
    # 使用 place 控制 LabelFrame 的位置
    frame_right.place(relx=0.5, rely=0.2, relwidth=0.3, relheight=0.6)
    label_1 = tk.Label(frame_right, text="C语言辅导班")
    label_1.place(relx=0.2, rely=0.2)
    label_2 = tk.Label(frame_right, text="数据结构")
    label_2.place(relx=0.6, rely=0.2)
    label_3 = tk.Label(frame_right, text="C++辅导班")
    label_3.place(relx=0.2, rely=0.6)
    label_4 = tk.Label(frame_right, text="Python答疑")
    label_4.place(relx=0.6, rely=0.6)
    win.mainloop()
    
    1.3.2.2 PanedWindow控件

    PanedWindow(窗格界面)也可以理解成一个特殊的 Frame 控件,它是 Tkinter 8.4 版本后新增的空间管理组件,其主要目的是为其他组件提供一个容器或者框架,从而实现以分块的形式对图形界面进行布局。

    与 Frame 控件不同, PanedWindow 允许用户自主地调整界面划分以及每块区域的大小。因此,当您需要让用户自己调节每块区域的大小时,就可以采用 PanedWindow 作为组件载体来进行界面的布局。

    不仅如此 PanedWindow 组件还提供了“手柄” 功能(设置参数 showhandle=True 来启用),通过拖动“手柄”图标也可以改变每块区域的大小。PanedWindow 组件语法格式如下所示:

    PanedWindow(master=None, **options) 
    

    其中 master 表示父组件,即包裹该组件的上层组件。其常用属性如下表所示:

    属性 说明
    handlepad 调节“手柄”的位置; 比如当 orient =‘vertical’ 设置垂直时,handlepad 表示“分割线”上的手柄与左端的距离,默认为 8 像素
    handlesize 设置“手柄”的尺寸(由于“手柄”必须是一个正方形,所以是设置正方形的边长)默认为 8 像素
    opaqueresize 该选项定义了用户调整窗格尺寸的操作,如果该选项的值为 True(默认),窗格的尺寸随用户鼠标的拖拽而改变 ,如果该选项的值为 False,那么窗格的尺寸,在用户释放鼠标时才会更新到新的位置上
    orient 指定窗格的分布方式,默认为水平方向分布(“horizontal”),或者还可以设置为垂直纵向分布(“vertical”)
    relif 指定边框的样式,默认为 “flat”,还可以设置为 “sunken”,“raised”,“groove” 或 “ridge”
    sashpad 设置每一条分割线到窗格间的间距
    sashrelief 设置分割线的样式,默认值是:“flat”,还可以设置 “sunken”,“raised”,“groove” 或 “ridge”
    sashwidth 设置分割线的宽度
    showhandle 设置是否显示调节窗格的手柄,默认为 False
    height/width 设置 PanedWindow 的高度、宽度,若不设置,则其大小由其子组件的尺寸决定

    PanedWindow 的常用方法如下表所示:

    方法 说明
    add(child) 添加一个新的子组件到窗格中语法格式 add(child,**option),参数值 after、before、sticky
    forget(child) 删除一个子组件
    panecget(child, option) 获得子组件指定选项的值
    paneconfig(child, **options) 设置子组件的各种选项
    panes() 将父组件中包含的子组件以列表的形式返回
    sash_coord(index) 返回一个二元组表示指定分割线的起点坐标
    sash_place(index, x, y) 将指定的分割线移动到一个新的位置

    下面示例设计一个简单的界面布局,然后将图形界面分割成四部分:创建一个水平方向的 PanedWindow,并向其中添加两个 Label 组件,之后创建一个垂直的方向的 PanedWindow,并向其中中添加两个 Label 标签。示例代码如下:

    import tkinter as tk
    win = tk.Tk()
    win.title("Python学习")
    win.geometry('400x400+200+200')
    win.iconbitmap('C:/Users/Administrator/Desktop/logo.ico')
    # 创建一个水平方向的 panedwindow,并添加到主窗口中,默认为水平方向
    p_window1 = tk.PanedWindow(win)
    p_window1.pack(fill=tk.BOTH, expand=1)
    # 在窗口区的左侧添加两个水平方向的 Label
    left1 =tk. Label(p_window1, text='Python', bg='#7CCD7C', width=10,font=('微软雅黑',15))
    p_window1.add(left1)
    left2 =tk.Label(p_window1, text='C++', bg='#9AC0CD', width=10,font=('微软雅黑',15))
    p_window1.add(left2)
    # 创建一个垂直方向的panedwindow,并添加一个手柄,设置分割线样式
    p_window2 = tk.PanedWindow(orient=tk.VERTICAL,showhandle=True,sashrelief='sunken')
    # 添加到 p_window1中
    p_window1.add(p_window2)
    # 在 p_window2 中添加两个垂直方向的标签
    top_label =tk. Label(p_window2, text='教程', bg='#7171C6', height=8,font=('宋体',15))
    p_window2.add(top_label)
    bottom_label =tk. Label(p_window2, text='辅导班', bg='#8968CD',font=('宋体',15))
    p_window2.add(bottom_label)
    win.mainloop()
    

    注意:从上述示例中可以看出 PanedWindw 会为每一个 Label 控件创建一个独立的窗格, 当我们将鼠标悬停在两个控件接壤处的白色边框上时,就会出现可以上下或者左右拉伸的指示光标,用户按照可以按照自己的意愿来调整每块区域的大小。

    1.3.2.2 Toplevel控件

    Topleve 是一个顶级窗口控件(也被称为“子窗体”控件),同样类似于 Frame 控件, 不过该控件会脱离根窗口另行创建一个独立窗口,因此它的存在形式不同于上述其他容器。

    Toplevel 控件同样隶属于主窗口的子组件,只是存在形式特殊而已。Toplevel 是主窗口之外的弹出框窗口(通过事件来触发执行),在这个窗口内也可以包含其他组件。但需要注意,顶级窗口并不是必须位于窗口的顶部位置,之所以称其为顶级窗口,是因为相对于主窗口而言,Topleve 位于主窗口的上一层。

    Toplevel 控件拥有根窗口控件的所有方法和属性,同时它还拥有一些独有的方法,如下表所示:

    方法 说明
    deiconify() 在使用 iconify() 或 withdraw() 方法后,即窗口最小化和移除窗口后(只是看不见,并没销毁),使用该方法来显示该窗口
    frame() 返回一个系统特定的窗口识别码
    group(window) 将顶级窗口加入 window 窗口群组中,如果忽略该参数,将返回当前窗口群的主窗口
    iconify() 将窗口图标化(最小化),需要重新显示窗口,使用 deiconify() 方法
    protocol(name, function) 将回调函数 function 与相应的规则 name 绑定;1) name 参数可以是 “WM_DELETE_WINDOW”:窗口被关闭的时候;2) name 参数可以是 “WM_SAVE_YOURSELF”:窗口被保存的时候;3) name 参数可以是 “WM_TAKE_FOCUS”:窗口获得焦点的时候。
    state() 设置和获得当前窗口的状态,参数值 “normal”(正常状态),“withdrawn(移除窗口)”,“icon”(最小化)和 “zoomed”(放大)
    transient(master) 指定为 master 的临时窗口
    withdraw() 将窗口从屏幕上移除,只是移动到了窗口之外,并没销毁,需要重新显示窗口,使用 deiconify() 方法

    下面看一组关于创建 Toplevel 的示例,如下所示:

    import tkinter as tk
    root = tk.Tk()
    root.config(bg='#87CEEB')
    root.title("Python学习")
    root.geometry('400x350+300+300')
    root.iconbitmap('C:/Users/Administrator/Desktop/logo.ico')
    def create_toplevel():
        top = tk.Toplevel()
        top.title("Python学习")
        top.geometry('300x200+100+100')
        top.iconbitmap('C:/Users/Administrator/Desktop/logo.ico')
        # 多行文本显示Message控件
        msg = tk.Label(top, text="Python学习",bg='#9BCD9B',font=('宋体',15))
        msg.pack()
    tk.Button(root, text="点击创建Toplevel组件",width=20,height=3,command=create_toplevel).pack()
    root.mainloop()
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » Python编写软件界面,打造出简洁易用的界面设计

    发表评论