《Python编程》第七章:图形化用户界面(tkinter)初识

概述

了解Python/tkinter的编码基础,主要使用一些简单的组件,包含:如何更好的创建组件、修改属性、pack、以及组件回调函数等;

tkinter程序的共同步骤

1.从tkinter模块中加载一个/多个组件类

2.创建该组件类的实例为标签类

3.在父组件中打包新标签

4.调用主循环,显示窗口,同时开始tkinter的事件循环;

mainloop方法最后执行,将标签显示在屏幕,进入tkinter等待状态,准备响应用户发起的GUI事件。mainloop函数中,tkinter内部会监控这些事件,如键盘活动、鼠标单击等;

子组件如何部署在父组件

举例:Label(None,text='Hello GUI world !!!').pack();

第一个参数是父组件对象,即:我们希望将新标签设置于其中。None,表示将新标签设置在该程序的默认顶层窗口;

第二个参数是标签配置选项。大多数组件的构造函数都能够接受多个关键字参数,对组件的颜色、尺寸、回调函数等进行具体设置

一、组件尺寸、标题修改及回调函数

1.组件尺寸、标题、无参数的回调函数

'''
expand=YES:可以让组件居中,并显示在扩展的空间中
fill选项:可用来拉伸组件,使其充满分配的空间;
fill=BOTH,xy轴都拉伸;fill=X:仅水平轴拉伸;fill=Y:仅垂直轴拉伸
'''
from tkinter import *
def msg():
    print("你很漂亮……")

root = Tk()
widget = Label(root,text='Hello GUI world!!!')
# widget.config(text='Hello GUI world!!!')#config方法,可以在组件创建后的任何时间被调用。
widget.pack(side=TOP,expand=YES,fill=BOTH)
#command=函数名,不要带括号,带上括号直接就运行了,不带括号只是调用,要等到触发才运行;
widget1 = Button(root,text='打印',command=msg)
widget1.pack()
#标题设置
root.title('gui1g.py')
root.mainloop()

2.带参数的回调函数

无参数的回调函数,组件在生成时,直接将command=函数名,即可成功实现回调函数;但是如果函数有参数,应该如何传参喃?要指导回调函数是不能直接加括号的,加括号就直接运行了,不会等待你触发事件才执行。

方式1:lambda匿名函数实现延迟调用

from tkinter import *
#lambda匿名函数实现延迟调用

def handler(A,B):
    print(A,B)
    sys.exit()
X=42
Button(None,text='HI',command=(lambda :handler(X,"spam"))).pack()
mainloop()

方式2:对象引用实现延迟调用

from tkinter import *
#对象引用实现延迟调用
def handler(A,B):
    print(A, B)
    sys.exit()
X=42
def func():
    #调用要实现的函数
    handler(X,'spam')
#command=中间函数
Button(None,text='HI',command=func).pack()
mainloop()

二、用类实现组件的生成

这个代码是下面两个例子的基础:

# -*-coding:utf-8-*-
#-*-md10_用类实现复用GUI部件.py-*-
from tkinter import *
class Hello(Frame):
    def __init__(self,parent=None):
        Frame.__init__(self,parent)
        self.pack()
        self.data = 42
        self.make_widgets()
    def make_widgets(self):
        #self即Hello本身,继承了Frame
        widget = Button(self,text='Hello frame world!',command=self.message)
        widget.pack(side=TOP)
        widget1 = Button(self,text='关闭',command=self.quit)
        widget1.pack(side=BOTTOM)

    def message(self):
        self.data += 1
        print('Hello frame world %s!'%self.data)

if __name__ == '__main__':
    Hello().mainloop()

下面的 代码引用上一个文件的类,实现模块化。

# -*-coding:utf-8-*-
from tkinter import *
from md10_用类复用GUI部件 import Hello

class HelloContainor(Frame):
    def __init__(self,parent=None):
        Frame.__init__(self,parent)
        self.pack()
        self.makeWidgets()
        
    def makeWidgets(self):
        #将上一个py文件中Hello类实现的组件一起添加打包到Frame上,实现模块化
        Hello(self).pack(side=RIGHT)
        Button(self,text='Attach',command=self.quit).pack(side=LEFT)
if __name__ == '__main__':
    HelloContainor().mainloop()

引用父类的函数实现组件部署,调用的却是子类本身的回调函数:

'''
扩展类部件
'''
from tkinter import *
from md10_用类复用GUI部件 import Hello

class HelloExtender(Hello):
    def make_widgets(self):
        Hello.make_widgets(self)
        Button(self,text='Extend',command=self.quit).pack(side=RIGHT)
    def message(self):
        print('Hello',self.data)

if __name__ == '__main__':
    HelloExtender().mainloop()

三、事件绑定

# -*-coding:utf-8-*-
import sys
from tkinter import *
def hello(event):
    print('Press twice to exit!!')

def quit(event):
    print('Hello,I must be going……')
    sys.exit()

widget = Button(None,text='Hello event world!!!')
widget.pack()
widget.bind('<Button-1>',hello)#鼠标左键1下触发hello
widget.bind('<Double-1>',quit)#鼠标左键2下触发quit
widget.mainloop()

四、独立的容器类

上面使用类完成组件的一些列过程,但是类本身都是基础了tkinter组件类的,即:类的实例对象就是一个组件,可以直接mainloop运行的下面代码使用思维:类本身不是组件,没有基础tkinter任何组件类,而在类里面去实现组件的一些列过程。即:类的实例不能直接mainloop运行

# -*-coding:utf-8-*-
from tkinter import *
class HelloPackage:
    def __init__(self,parent=None):
        self.top = Frame(parent)
        self.top.pack()
        self.data = 0
        self.make_widgets()
    def make_widgets(self):
        Button(self.top,text='Bye',command=self.top.quit).pack(side=LEFT)
        Button(self.top,text='Hye',command=self.message).pack(side=RIGHT)

    def message(self):
        self.data +=1
        print('Hello number',self.data)

if __name__ == '__main__':
    # 所有的组件都在Frame上,而HelloPackage并不是组件,只是一个类(用来存储真实组件对象及信息);
    # 所有的组件依附于self.top,若我们要启动GUI,就需要self.top.mainloop();而不是self.mainloop()
    HelloPackage().top.mainloop()

对上面独立的容器类的引用:

from tkinter import *
from md14_独立的容器类 import HelloPackage

frm = Frame()
frm.pack()
Label(frm,text='hello').pack()

part = HelloPackage(frm)
part.top.pack(side=RIGHT)#注意:这里必须要一个top,因为HelloPackage类只是一个容器类,所有组件依附于self.top
frm.mainloop()

比较完美的解决方式是:通过定义方法将获取的不明属性引导至内嵌至的Frame;

步骤1:创建一个获取类属性的中间类

#引用上面的py文件
from md14_独立的容器类 import HelloPackage
from tkinter import *

class HelloPackage(HelloPackage):
    def __getattr__(self, item):
        return getattr(self.top,item)#完成并传递到一个实际的组件

步骤2:再引用上面的类

from tkinter import *
from md15_config import HelloPackage

frm = Frame()
frm.pack()
Label(frm,text='hello').pack()

part = HelloPackage(frm)
part.pack(side=RIGHT)
frm.mainloop()

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷凝娇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值