《Python编程》笔记(七)

图形化用户界面

  • Python中可以使用的主要GUI工具包:

    • tkinter:开源GUI库,作为Python业界开发移动GUI约定俗成的标准,拥有Pmw, Tix, PILttk等强大的扩展包。
    • wxPython:一个用于开源wxWidgets库,最初为C++编平台GUI类框架。适合复杂界面搭建,流行度jinciyutkinter
    • PyQt:一个全面的GUI库,跨越多个平台。相对复杂,但有更多特性。
    • PyGTK:用于连接GTK的库,可以跨平台。
    • Jython:一款针对Java的Python应用,可以将Python转换为Java字节码,完成Python语言与Java类库的无缝连接。所以可以使用Java中的swingawt等实现用户界面。
    • IronPython:一款针对.Net环境和runtime engine的Python应用,可以将Python代码转换成.Net字节码,同时支持在.Net架构下用Python脚本搭建GUI界面。
  • tkinter的特点:

    • 可访问性:一个轻量级的工具包,非常易用。并且易于扩展。
    • 可移植性:能够在不同的平台下提供本地化特色的界面。
    • 可用性:它是Python库中的标准模块,自带编译器。
  • tkinter扩展包介绍:

    • Pmw:Python Mega Widgets是用Python建立高级复合组件的扩展工具包。可以提供满足高级GUI开发的需要。该组件的接口与基本dtkinter组件类似。
    • Tix:含有40多个高级组件的集合,最初为Tcl/TK编写。可以在tkinter.tix中得到它。
    • ttk:一个比较新的组件集,试图区分两类代码,一类负责执行组件行为,另一类负责实现不同的组件外观。该包在tkinter.ttk中。
    • PIL:Python Imaging Library是一个开源图像处理扩展包,提供缩放、变形、转换等工具,支持多种图像文件类型。
  • Python的tkinter模块在Tk(最初用Tcl语言编写,由Tcl创立者John Outerhout开发)之上增加了一个软件层,该层允许Python脚本与Tk对话,进行界面的构建和配置,再经路径控制回到处理用户事件的Python脚本。内部调用顺序:从Python脚本到tkinter,再到Tk;GUI事件的响应顺序则是从Tk到tkinter再到Python脚本。

  • Python tkinter是在C编写的_tkinter(实际是它与Tk交互)库之上增加了基于类的交互界面。Python/tkinter程序是事件驱动的。

  • 简单的示例:

# 导入Label组件
from tkinter import Label

# 获取Label对象实例
widget = Label(None, text="Hello, tkinter!")

# 布局
widget.pack()

# 开始事件循环
widget.mainloop()
  • 创建组件:
    • 第一个参数是父组件对象,设置为None表示将新的组件设置在程序的默认顶层窗口。当然也可以将组件放置到其他容器中。
    • 第二个参数是配置参数。
      http://blog.chriscabin.com/
  • tkinter几何管理器只是安排一个或多个组件在容器(父组件)内的位置,顶层窗口和框架(一种特殊组件)都可以作为容器;容器可以嵌套,显示出层级结构。常用的有两种:打包pack和网格grid
  • 在Windows下,.pyw.py结尾的Python程序在双击运行时表现是不同的,前者不会弹出DOS控制台作为它的标准流。实际上.pyw文件最好用pythonw程序打开。
  • widget.pack(side=TOP)TOP常量在pack中被调用,它是tkinter的专有名字之一。常量模块由tkinter自动加载。
  • 对组件使用pack时,可以选择组件在父组件中的位置:顶、底、左、右。如果不设置位置,则默认放在父组件的顶部。
  • root=Tk()可以得到主窗口,即程序运行时就会出现的窗口。组件如果不设置父组件,则默认依附于自动创建的Tk实例(主窗口)。
# 不用显示地指定root,此时master会被设置为自动创建的Tk对象
Label(text='Hello, Left.').pack(side=LEFT)
Label(text='Hello, Right.').pack(side=RIGHT)
Label(text='Hello, Top.').pack(side=TOP)
Label(text='Hello, Bottom.').pack(side=BOTTOM)
mainloop()

  • Label(text='Hello, Top.').pack(side=TOP, expand=YES, fill=BOTH)

    • expand=YES要求打包几何管理器为组件扩展空间,通常可以是父组件中任何未被占用的地方。仅使用该项,而不加fill选项,会自动居中组件。
    • fill选项:可用来拉伸组件,使其充满分配的空间。fill=Y表示垂直拉伸,fill=X表示水平拉伸,fill=BOTH表示都拉伸。
  • 设置组件选项的另外两种方法:

>>> label.config(text="Good")
>>> label['text'] = "Yahoo"
  • 设置窗口标题:Tk().title("Hello, world")
  • tkinter在内部将组件对象交叉连接成一棵可以长期存在的树,该树代表了要显示的对象。所以,即使Python中,对象被垃圾回收,但是在tkinter中还是会被保留下来。
  • 添加按钮和回调函数的方法:
def button_demo():
    root = Tk()
        # 实际上sys.exit和root.quit都能得到相同的效果
        # command就是记录按钮单击后的回调行为
    Button(text="Exit", command=root.quit).pack(side=TOP, expand=YES)
    root.mainloop()
  • 回调处理器通常可以是任何可调用的对象:函数、lambda表达式生成的匿名函数、类或者类型实例的绑定方法,或者是继承了__call__运算符重载方法的实例。当按钮按下发生回调时,回调处理器不会接受到任何参数(除了自动为绑定方法生成的self参数),回调处理器需要的状态信息必须以其他方式提供,如全局变量、类实例的属性、间接层提供的额外参数等。
  • 使用lambda表达式和对象引用来延迟调用:这时一种比较常见的技巧,可以将不带参数的回调映射到另一个由lambda提供参数的函数上:
def handler(widget, x, y):
    widget.configure(text='{} * {} = {}'.format(x, y, y))


def button_demo_2():
    label = Label()
    label.pack(side=TOP, expand=YES)
        # 可以延迟对真正的回调函数的调用
    Button(text='Press me!', command=lambda: handler(label, 88, 109)).pack(side=BOTTOM,  expand=YES)
    mainloop()

  • 延迟回调是有必要的(通常都是需要接受参数的回调函数),如果在按钮创建函数中编写回调处理器调用,那么回调函数会在创建按钮的同时被调用。所以,必须要使用中间函数来延迟调用。
  • Python的封闭作用域引用模型意味着函数局部作用域内包含lambda函数的局部变量值会被自动保留,并且在按钮按下时使用。
  • 默认参数与外部作用域引用不同,它在函数创建时定值,而不是调用时定值。它可以记录函数创建时封闭作用域内名字的值,而不是封闭作用域内某个地方最后分配的值。当函数的作用域是一个模块而不是另外一个函数时,也是如此。这些是在GUI注册回调函数时需要注意的。
>>> def odd():
    funcs = []
    for c in 'abcdefg':
      # 如果是lambda: c,则在后面调用后会出现同样的信息。
        # 使用默认参数传值才可以记住c
        funcs.append(lambda c=c: c)
    return funcs
>>> for x in odd():
    print(x())
  • 总结:封闭作用域名字引用可以作为默认参数传值的替代之选,但是有条件:封闭作用域中的名字不会在内嵌函数创建后变成其他不知道的值。通常,不能在内嵌函数内部引用封闭作用域的循环变量,然而,在其他大多数情况下,封闭作用域的循环变量在其作用域中只有一个值,这样才可以被自用地使用。但相对来说,类是一种更好的处理方法,它可以用来保存需要的额外信息,也不会出现作用域的问题。
  • 使用类中的方法作为回调函数:
class MyGUI:
    def __init__(self):
        self.x = 100
        self.y = 100
        self.label = Label()
                # 注意,pack返回的是None
        self.label.pack(side=TOP, expand=YES)
        Button(text="Press to get result", command=self.get_result).pack(side=TOP, expand=YES)
        Button(text='Quit', command=sys.exit).pack(side=TOP, expand=YES)

    def get_result(self):
        self.label.config(text='{} * {} = {}'.format(self.x, self.y, self.x * self.y))


def main():
    MyGUI()
    mainloop()
  • 再来看看另外一种方法来设定回调函数:可调用类对象
class HelloCallable:
    def __init__(self):
        self.msg = 'Hello __call__ world!'

    def __call__(self, *args, **kwargs):
                # 重要的是继承了__call__方法后,就可以让类对象像普通函数那样被调用。
        print(self.msg)
        sys.exit()

# 注意,`HelloCallable()`才可以工作!
Button(text='Quit', command=HelloCallable()).pack(side=TOP, expand=YES)
  • tkinter回调协议总结:

    • 按钮的command选项:捕捉按钮按下事件。
    • 菜单的command选项:捕捉菜单按下事件。
    • 滚动条协议:同样使用command注册处理器,但是包含一个独特的事件协议,允许它们与被滚动的组件交叉组合,即移动滚动条就会自动移动组件,反之亦然。
    • 一般的组件bind方法:这种机制可以用来为低级别的界面事件注册回调处理器,比如按键、鼠标等。bind调用会接收一个事件对象参数(Event实例),它会提供事件的环境信息。
    • 窗口管理器协议:捕捉窗口管理器事件。在顶层窗口的对象管理器里面输入protocol方法,为WM_DELETE_WINDOW设置处理器。
    • 预定的事件回调:如定时器过期、输入数据到达、事件循环的空闲状态等。
  • 在框架(Frame)组件中添加多个组件:

class MyGUI:
    def __init__(self):
        self.win = Frame()
        self.win.pack(expand=YES)
        Label(self.win, text="Hello, container world!").pack(side=TOP)
        Button(self.win, text="Hello", command=lambda: print('Hello, container world!')).pack(side=LEFT)
        Button(self.win, text="Quit", command=self.win.quit).pack(side=RIGHT)

def main():
    MyGUI()
    mainloop()

  • 先打包的组件会在窗口收缩后最后剪裁,所以打包的顺序决定了窗口缩小后那些组件会被先挤出去。
  • 一般地,通过将组件依附于框架,再将框架依附于其他框架,我们可以搭建出任意的GUI布局。
  • 当组件树显示时,孩子组件出现在父组件内部,并且按照打包顺序好打包位置排列。所以说,组件的打包顺序不仅决定了它们的裁切顺序,还决定了它们在生成的显示中相互间边的位置关系。
  • packer布局系统的工作原理:

    • packer最初拥有整个父组件容器的可用空间;
    • 随着组件在某条边上被打包,该组件获得了剩余空间要求的一条边,剩余空间缩小;
    • 经过先前的打包要求,空间缩小,后来的打包仅要求获得剩余空间中的一条边;
    • 组件全部分配后,expand选项划分所有剩余空间,fill选项和anchor选项在组件分配的空间内拉伸调整组件。
  • anchor选项可以定位分配空间中的位置替代fill选项。可以指定八个方位(指南针:N, NE, NW, W, S等)以及CENTER位置。默认就是CENTER。

  • fill选项和anchor选项必须在组件分配到所在空间、完成打包顺序、expand要求后才可以使用。通过一起使用打包顺序、边、填充和定位,可以产生多种布局和剪裁效果。
  • 大型GUI界面通常作为Frame子类创建,用回调处理器作为方法。
class HelloFrame(Frame):
    def __init__(self, parent=None):
        Frame.__init__(self, parent)
        self.pack()
        self.data = 20
        self.make_widgets()
    def make_widgets(self):
        w = Button(self, text="hello", command=self.msg)
        w.pack(side=LEFT)
    def msg(self):
        self.data += 1
        print('Hello frame world!', self.data)
  • 技巧:要改变GUI的行为,可以写一个新类来自定义它的相关部分,而不是改写现有的GUI代码。
  • tkinter组件类:
组件类描述
Label显示简单消息区域
Button带有标签的简单的按钮
Frame用于盛放和布置其他组件对象
Toplevel, Tk由窗口管理器管理的新窗口
Message一个多行标签
Entry简单的单行文本输入区域
Checkbutton双状态按钮组件,用于多选
Radiobutton双状态按钮组件,用于单选
Scale可衡量位置的滑动组件
PhotoImage图像组件,全彩图
BitmapImage图像组件,位图
Menu菜单相关
Menubutton打开菜单选项和子菜单的按钮
Scrollbar滚动其他组件的控件
Listbox选项列表
Text多行文本浏览、编辑组件,支持字体
Canvas图形绘画区域,支持线条、圆圈、照片、文字等

- 重要的类和工具:
- 几何管理器:pack, grid, place
- tkinter连接变量:StringVar, IntVar, DoubleVar, BooleanVar
- 高级Tk组件:SpinBox, LabelFrame, PanelWindow
- 复合组件:Dialog, ScrolledText, OptionMenu
- 回调安排:组件的after, wait, update方法;
- 其他:标准对话框、剪切板、bindEvent,组件设置选项,用户对话框、模式对话框、动画等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python学习笔记PDF是一种学习Python编程语言的资料形式,它包含了Python的基本语法、数据类型、流程控制、函数、模块、面向对象编程、异常处理等相关内容。以下是关于Python学习笔记PDF的详细内容说明: 1. 基本语法:Python学习笔记PDF中,首先介绍了Python的基本语法,例如如何定义变量、数据类型的使用(包括整数、浮点数、字符串、列表、元组、字典等),以及如何进行算术运算、比较运算和逻辑运算。 2. 流程控制:Python学习笔记PDF中,进一步介绍了流程控制的知识,包括条件判断和循环控制。条件判断主要是通过if语句进行判断执行不同的代码块,而循环控制则通过while循环和for循环来实现重复执行一段代码。 3. 函数:Python学习笔记PDF中,对函数的概念和使用进行了详细的解释。函数是代码的封装和组织方式,通过定义函数可以提高代码的重用性和可读性。学习者将了解到如何定义函数、调用函数、函数参数的传递以及函数返回值的使用。 4. 模块:Python学习笔记PDF中,介绍了Python中的模块和包的概念。模块是一组函数、类或变量的集合,以.py文件的形式存在,可以被其他程序调用和使用。学习者将学习如何导入模块、使用模块中的函数和变量。 5. 面向对象编程Python学习笔记PDF中,对面向对象编程进行了系统的讲解。面向对象编程是一种以对象为基本单位的编程思想,通过定义类和对象,可以更好地组织和管理代码。学习者将了解如何定义类、创建对象、封装、继承和多态的使用。 6. 异常处理:Python学习笔记PDF中,对异常处理进行了介绍。异常是程序在运行过程中出现的错误,通过捕获和处理异常,可以更好地控制程序的执行流程并提高程序的健壮性。学习者将了解到如何使用try-except语句来捕获和处理异常。 总之,Python学习笔记PDF是一份全面而详细的学习Python编程语言的资料,通过学习该资料,学习者将获得扎实的Python编程基础,并能够运用Python进行简单的程序开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值