运行在计算机上的程序一般分为命令行程序和图形界面程序,例如:安装Python三方模块的pip命令,软件版本管理的git命令等都属于命令行程序;而大多数软件使用图形界面,例如Windows的Word,Excel,画图等等软件都是图形化用户界面,简称GUI。

在图形化用户界面中,用户可以用鼠标操作菜单、按钮等图形化组件,并从对话框等图型化组件中获取信息。实现图形化界面的方法与制作游戏界面的流程相似:在初始化工具之后,进入主循环接收用户事件,并且进行显示、反馈等处理,直到程序退出,才结束主循环。与绘制游戏界面不同的是,游戏界面中的绘图、处理鼠标事件都需要开发者写程序自行处理,而图形用户界面内部已经实现了按钮、文本框的绘制和响应事件,使用时调用这些控件即可,减少了编写程序的工作量。

图形界面在任何编程语言中原理都一样,本讲通过Python图形界面编程,介绍图形界面中的基本概念和简单用法:常用控件、布局方法、事件处理。

16.1 图形界面入门

Python的图形用户界面常使用Tkinter开发,Tcl 是“工具控制语言”的缩写。Tk是Tcl“图形工具箱”的扩展,而Tkinter是Tk interface的缩写,意思是TK界面。

在Windows系统中Tkinter已由Anaconda安装,可以直接使用,在Linux下则需要使用apt安装python3-tk软件包。

16.1.1 基本概念

在学习具体编程之前,先了解一些基本概念。

1.控件

控件也叫组件,是图形用户界面中最基本的组成部分,常用的控件有:按钮、文本框、标签、表格等等。

2.容器

容器是一种特殊的控件,它能容纳其它控件,如窗口、对话框都属于容器。

3.布局

布局是控制控件在容器中的大小和位置的方法。

4.事件处理

事件是可以被程序识别的操作,如:按下按钮,选择某个单选按钮或者复选框,关闭程序等等,开发者往往需要对事件做出处理,响应某个事件的函数就是事件处理程序,也被称为回调函数。

16.1.2程序示例

下例是一个简单的图形界面程序,它创建窗口。并在窗口中显示两行文字“test1”和“test2”。

01 import tkinter

02

03 win = tkinter.Tk()

04 win.geometry("320x240+200+50")

05 tx1 = tkinter.Label(win, text="test1")

06 tx1.pack()

07 tx2 = tkinter.Label(win, text="test2")

08 tx2.pack()

09 win.mainloop()

第01行引入tkinter模块。

第03行创建一个实例,用于显示窗口。

第04行设置窗口大小为:宽度320,高度240,位置在屏幕横坐标200,纵坐标50。

第05行创建标签控件tx1用于显示文字,Label函数有两个参数,第一个参数指定控件所在的容器,第二个参数text指定标签上显示的文字。

第06行将控件放置在容器之中,pack是布局的一种方法,将在之后的“布局”部分详细介绍。

第07-08行创建和放置了第二个标签tx2。

第09行开启主循环,在窗口关闭时主循环退出,程序结束。

程序运行结果如图16.1所示:

16.1 简单的图形用户界面

16.2 布局

布局是把控件放置到容器之中,并且指定放在哪里,以及如何放置。Tkinter有3种基本布局管理器:pack、grid和place,还提供容器Frame支持复杂的嵌套布局。

16.2.1 常用布局方法

1. pack布局

pack是最常用的布局方法——顺序布局,用于按顺序添加各个控件,上例中使用pack分别添加了两个文字标签,可以看到控件按添加的顺序依次显示在窗口中。图16.2分别展示了横向和纵向顺序布局的方法。

图16.2 pack布局示意图

其基本语法如下:

01 控件名.pack(可选参数)

布局的可选参数如表16.1所示:

表16.1 布局参数表

2.grid布局

grid按网格摆放控件,如图16.3所示,其中每个控件的位置都由行索引row和列索引colomn两个值确定,索引号从0开始(不是1),如左上角的控件1行列为0,0;控件2行列为0,1,以此类推。

图16.3 grid布局示意图

其基本语法如下,该函数也支持表16.1中的参数。

01 控件名.grid(row=行索引, column=列索引,可选参数)

3.place布局

place按具体坐标摆放控件。如图16.4所示,用x1,y1设置控件1左上角的位置。

图16.4 place布局示意图

其基本用法如下,该函数也支持表16.1中的参数。

01 控件名.place(x=横坐标, y=纵坐标,可选参数)

16.2.2 容器布局

当界面设计比较复杂时,一般使用Frame容器实现布局。Frame译为框架,它是一种容器,容器是可以包含其它控件的特殊控件。图16.5在同一窗口中加入了11个控件,包含顺序和网格两种布局方法,实现此界面,需要建立两个frame容器,一个容器为深色背景,用于存放控件1和控件2,另一个容器为浅灰色背景,用于存放其它网络布局的控件。Frame本身也是控件,两个frame控件也使用了顺序布局。

图16.5 frame容器示意图

其基本语法如下。

01 f= Frame(父容器,可选参数)

以上程序创建了容器f,之后可以将其它控件加入该容器。“父/子”用于描述容器和控件之间的关系,通常将包含其它控件的容器称为“父”,而被包含的控件被称为“子”。

16.2.3 综合实例

本例中使用了pack、grid、place、frame多种方法布局界面。

01 import tkinter

02

03 win = tkinter.Tk()

04 win.geometry("320x240+200+50")

05

06 f1 = tkinter.Frame(win)

07 f1.pack()

08 f2 = tkinter.Frame(win)

09 f2.pack()

10

11 tx1 = tkinter.Label(f1, text="test1")

12 tx1.grid(row=0,column=0)

13 tx2 = tkinter.Label(f1, text="test2")

14 tx2.grid(row=1,column=1)

15 tx3 = tkinter.Label(f2, text="test3")

16 tx3.pack()

17 tx4 = tkinter.Label(win, text="test4")

18 tx4.place(x=10,y=10)

19

20 win.mainloop()

第01-04行用于引入模块和创建窗口。

第06行创建容器f1,并指定其父容器为窗口。

第07行用pack方法将容器以顺序方式布局。

第08-09行建立并加入了第二个容器f2。

第11行创建标签控件tx1,设置其父容器为f1。

第12行用网格方式布局tx1显示在网格的第0行0列。

第13-14行创建标签控件tx2,并以网格方式布局tx2显示在网格的第1行1列。

第15行创建标签tx3,设置其父容器为f2。

第16行用顺序方式将控件tx3布局到其父容器中。

第17行创建标签tx4,设置其父容器为窗口win。

第18行用指定具体位置的方式将控件布局到窗口的坐标为(10,10)位置上。

第20行开启主循环,在窗口关闭时主循环退出,程序结束。

程序运行结果如图16.7所示,其中深灰色部分为容器f2,浅灰色部分为容器f1,它们大小不同是由于容器大小等于其子控件大小。f1中子控件更多,因此区域更大。

图16.6 布局综合实例运行结果

16.3 控件

Tkinter除了标签控件Label,还支持很多其它控件,本节将介绍最为常用的:按钮、输入框、选择框、以及显示图片的控件。

16.3.1 常用控件

1.标签

标签控件用于显示文字或者图片,定义方法如下:

01 tkinter.Label(父容器, [可选参数])

控件常用的可选参数如表16.2所示:

表16.2 控件常用参数

2.按钮

按钮控件是最常用的控件,例如对话框中的“确定”、“取消”都用按钮控件实现。定义方法如下:

01 tkinter.Button(父容器, [可选参数])

3.输入框

输入框显示为矩形框,供用户输入信息使用。定义方法如下:

01 tkinter.Entry(父容器, [可选参数])

4.选择框

一般情况下,选择框前面是一个矩形方框,后面跟随说明文字,例如:让用户选择“婚否”,结婚则在矩形方框中打钩,否则留空。定义方法如下:

01 tkinter.Checkbutton(父容器, [可选参数])

5.图片

图片不直接作为控件使用,而是作为标签或者其它控件的背景,如果不设置标签文字,只设置其背景图片,则该标签是一个图片标签。图片的加载方法如下:

01 tkinter.PhotoImage(file=图片路径)

图片加载后,可放在控件的可选参数image中使用。

16.3.2 获取和设置控件的属性

属性指的是控件的性质,一般在创建控件时指定,如:控件的宽度width,高度height等,查看控件的属性方法类似于访问字典,具体方法如下:

01 控件变量名[属性名]

使用configure方法可以重新设置控件属性值,使用方法如下:

01 控件变量名.configure(属性名=属性值)

下例是操作属性的实际应用:

01 x = tkinter.Label(win, text=”abcd”)

02 print(x[‘text’])

03 x.configure(text=’efg’)

第01行建立了标签控件,并设置标签显示的文字:text属性为“abcd”。

第02行显示出控件变量x的text属性。

第03行修改控件变量x的text属性为“efg”。

16.3.3 综合实例

下面通过综合实例,进一步巩固本节中介绍的各个控件的用法。

01 import tkinter

02

03 win = tkinter.Tk()

04 label = tkinter.Label(win,text="请填表") # 创建文字标签控件

05 label.pack()

06 img = tkinter.PhotoImage(file='bird.png') # 加载图片

07 label_img = tkinter.Label(win,image=img) # 创建图片标签控件

08 label_img.pack()

09 entry = tkinter.Entry(win) # 创建输入框控件

10 entry.pack()

11 check = tkinter.Checkbutton(win,text="婚否") # 创建选择框控件

12 check.pack(anchor='w')

13 button = tkinter.Button(win, text="退出") # 创建按钮控件

14 button.pack()

15 win.mainloop()

程序运行结果如图16.7所示:

16.7 控件综合实例运行结果

课后练习:(练习答案见本讲最后的小结部分)

练习一:绘制如图16.8所示的计算器界面,其中上方用Label显示输入数值和计算结果,下方提供12个按钮用于输入数字和符号。

图16.8 计算器效果图

16.4 事件处理

程序需要接收用户操作,并进行反馈。用户操作和系统发来的信息统称事件,事件又分为两种,一种是与整个窗口相关的事件,比如关闭窗口,另一种是与单个控件相关的事件,比如按下按钮Button产生的事件。

16.4.1 控件事件处理

在创建按钮时,可通过command参数设置当按钮按下时调用的函数,即事件响应函数,用法如下例所示:

01 def do_1():

02 print("按下1")

03

04 bt=tkinter.Button(win, text='1',command=do_1)

05 bt.pack()

第01-02行定义了事件的响应函数do_1,并在函数中显示字符串“按下1”。

第04行创建按钮控件,并指定按下按钮时调用函数do_1(注意:本行do_1函数并未被调用)。

16.4.2 窗口事件处理

在创建按钮时,可通过protocol设置窗口相关事件的响应函数。下例为设置窗口关闭事件,在窗口关闭时自动调用fun1函数。

01 import tkinter

02

03 def func1():

04 print("关闭窗口")

05 win.destroy()

06

07 win = tkinter.Tk()

08 win.geometry("400x400+200+50")

09 win.protocol("WM_DELETE_WINDOW",func1)

10

11 win.mainloop()

第03行定义事件响应函数fun1。

第04行显示字符串"关闭窗口"。

第05行调用窗口的destroy方法销毁窗口。

第09行设置在窗口关闭时调用自定义函数fun1,即关联事件和响应函数。

课后练习:

练习二:继续完成上题中计算器程序,响应用户按下各个按钮的事件,更新Label显示算式,在用户按下”=”按钮时,计算算式结果。

(提示:Python的eval函数用于执行字符串表达式,例如eval(“1+2”)的结果为3;十二个按钮功能类似,建议先将其中一两个按钮调试正常后,用复制粘贴的方法实现其它按钮,以免在调试过程中反复修改)。

16.5 思维训练

16.5.1 眼中的世界

人们对客观事物比如什么是一、二、三、花、草、树木有着类似的理解,有了这些共识,可以通过语言来沟通;这也让我们误认为,每个人眼中的世界都是相同的。

然而,“一千个读者眼里有一千个哈姆雷特”,不仅是故事,人们对单个文字的理解也不尽相同。对于什么是“爱”,什么是“道德”,这些并非具体可见的事物,由于文化和经历不同,大家的理解也不尽相同,越是不能用语言描述的感觉,差异可能越大。

为什么有些笑话,只有大人才觉得有趣,因为孩子并不知道很多语言的二义性以及背后的引申含义,艺术家激活了大家拥有的共同体验,它们又往往是不可言喻的。引领着读者的思维在具体文字图像和感觉之间跳跃。

语言是一种抽象的符号,是人们交流的工具,却不是现实或思维本身。任何事物或者词汇的意义都取决于它与其它事物的关系,从而形成了脑中复杂的关系网络,而不是简单的字典上的定义。

16.5.2 用语言思考

在表达的过程中,思维本身也在变化,表达过程中可能创造出一些新的想法,这就是“用语言思考”。对于复杂的内容,无法用语言描述它的所有细节,在表达的过程中,必然经过提炼和简化,这也重构了思维状态。因此,有时候向别人提问的过程中,自己就找到了答案。

语言的结构以链式为主,而思维内部一般是网状连接,描述过程是将一团相互纠缠的细网拆解成为一条主链。当一个人用语言的标号代替一套复杂的结构,就可能建立和处理更加复杂的内容。想要利用语言在他人脑中重建自己脑中的思维结构,必须掌握网状和链状结构相互转换的能力,同时还要了解大家头脑中的“共识”。

比如写一部小说或者电影的观后感就是一种总结和梳理,从文章的内容和结构上也能看到写作者的思路和关注点。练习作文或者写程序,不只是掌握语言本身,也是锻炼总结、抽象的能力。这种能力必须通过不断地书写、修改、总结来增强。

虽然很多思维与语言无关,比如触觉、味觉、情绪,不一定能用语言精确地表达出来,但我们仍然常用语言来思考问题,比如常常听到小孩自言自语,成人思考问题,有时也像在脑中独白或者与人对话,这都是语言赋予我们的思考方式。

16.5.3 语言以外的表达方式

语言是一种链式的表达方式,除了简单,它还有利于推导,归因……但是,脑中的结构往往更加复杂,比如下图中的关系,虽然可以用语言描述,但是非常麻烦。除了各个部件之间的关系,描述时还需要考虑如何遣词造句,这就把问题变得更加复杂。

图16.9 关系图

流程图,思维导图,公式,程序,它们不仅与自然语言的语法不同,结构也不同。在不同情况下,可采用不同的表达方式,如果做数学应用题的时候也用画图的方法,换一种角度表达,可能描述本身就是问题的答案。

16.5.4 学习语言

霍金曾说:多写一个公式就会吓跑一半读者,英国一项研究证明:数学公式不但会吓跑普通读者,科学家也会被公式吓跑。这主要由于日常生活中并不经常使用公式。学习语言需要大量时间。自然语言是这样,公式和程序语言也一样,需要反复学习和使用才能记忆。

脑中没有大量的存储空间用于记忆,即使空间足够,从海量信息之中查找也需要大量时间。因此,只有反复使用的内容才能被记住。也只有掌握了语言,才可能利用它思考和解决问题。学任何一门非母语的语言都有很大难度,甚至大多数人对母语掌握得也没有想象中那么好,比如很少有人能驾驭小说、新闻等不同风格的文章写作。

写作的人将脑中的思维框架转换成文字,并试图在读者脑中构建起类似的结构,其中包括着大量的常识和背景知识,比如通过故事发生的时间、地点、氛围、故事风格,激活读者脑中的某种场景,这些都是文字之外的信息。思维中故事的框架是多层次的网络,而机器所识别的文字只是相对扁平的结构。

通过前几讲的学习可以看到,目前机器学习模仿写武侠小说的能力已经非常强大,而小说的风格明显不适合写新闻。如果想训练机器写所有类型文章,则需要使用非常大量的数据训练模型,让它拥有基本写作能力。然后再根据要生成的不同文章类型,定向训练。机器有海量的存储和算力,但不是每个人都有时间和条件作大规模的训练。

学习自然语言也一样,如果希望读懂新闻,对话,科技论文,就需要非常大量的训练,不如想看论文,就主要读论文,当然,练习“阅读论文”对“对话水平”提高有限。

16.6 小结

16.6.1单词

本讲需要掌握的英文单词如表16.3所示。

表16.3本讲需要掌握的英文单词

16.6.2习题答案

1.练习一:绘制如图16.8所示的计算器界面,其中上方用Label显示输入数值和计算结果,下方提供12个按钮用于输入数字和符号。

2.练习二:继续完成上题中计算器程序,响应用户按下各个按钮的事件,更新Label显示算式,在用户按下”=”按钮时,计算算式结果。

01 import tkinter

02

03 win=tkinter.Tk()

04

05 f1=tkinter.Frame(win)

06 f1.pack()

07 f2=tkinter.Frame(win)

08 f2.pack()

09

10 label=tkinter.Label(f1,text="")

11 label.grid(row=0,column=0)

12 def do_1():

13 y=label['text']

14 x=str(1)

15 s=y+x

16 label.configure(text=s)

17

18 bt1=tkinter.Button(f2,text='1',command=do_1)

19 bt1.grid(row=1,column=0)

20 def do_2():

21 y=label['text']

22 x=str(2)

23 s=y+x

24 label.configure(text=s)

25

26 bt1=tkinter.Button(f2,text='2',command=do_2)

27 bt1.grid(row=1,column=1)

28 def do_3():

29 y=label['text']

30 x=str(3)

31 s=y+x

32 label.configure(text=s)

… # 此处省略其它数字

90 btjia=tkinter.Button(f2,text='+',command=do_jiahao)

92 btjia.grid(row=4,column=1)

93 def do_dengyu():

94 y=label['text']

95 t=str(eval(y))

96 label.configure(text=t)

97

98 btd=tkinter.Button(f2,text='=',command=do_dengyu)

99 btd.grid(row=4,column=2)

100 def do_jianhao():

101 y=label['text']

102 x=str('-')

103 s=y+x

104 label.configure(text=s)

… # 此处省略乘除运算

132 win.mainloop()

3.练习三:总结常见错误信息及其原因。

python少儿图形编程_少儿Python编程_第十六讲:图形界面开发相关推荐

  1. (转载)VS2010/MFC编程入门之五十二(Ribbon界面开发:创建Ribbon样式的应用程序框架)...

    上一节中鸡啄米讲了GDI对象之画刷CBrush,至此图形图像的入门知识就讲完了.从本节开始鸡啄米将为大家带来Ribbon界面开发的有关内容.本文先来说说如何创建Ribbon样式的应用程序框架. Rib ...

  2. python pipeline框架_Python爬虫从入门到放弃(十六)之 Scrapy框架中Item Pipeline用法...

    原博文 2017-07-17 16:39 − 当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理 每个item pipeline组件是实现了简单的方法的pytho ...

  3. (转载)VS2010/MFC编程入门之五十四(Ribbon界面开发:使用更多控件并为控件添加消息处理函数)...

    上一节中鸡啄米讲了为Ribbon Bar添加控件的方法.本节教程鸡啄米将继续完善前面的实例,讲解一些稍复杂的控件的添加方法,及如何为它们添加消息处理函数. 一.为Ribbon Bar添加更多Ribbo ...

  4. Python实战从入门到精通第十六讲——匿名函数捕获变量值

    用lambda定义了一个匿名函数,并想在定义时捕获到某些变量的值. 先看下下面代码的效果: >>> x = 10 >>> a = lambda y: x + y & ...

  5. java宏定义_现代化的 Java (二十六)—— Akka Stream Graph

    Java. 的 Stream API,有经验的 Java 工程师应该都不陌生了.它为数据处理逻辑提供了一组串化的操作序列接口,为流式的业务提供了一个整齐一致的接口.但是要指出的是,在常见的编程语言中, ...

  6. 二十六、图形用户界面

    1984年苹果发布的Macintosh是普通人可以买到的第一台带图形用户界面的计算机.在那个命令行计算机为主的时代里,这是一个革命性的产品.图形用户界面是一个"选择并点击"(poi ...

  7. 卷积核和全连接层的区别_「动手学计算机视觉」第十六讲:卷积神经网络之AlexNet...

    前言 前文详细介绍了卷积神经网络的开山之作LeNet,虽然近几年卷积神经网络非常热门,但是在LeNet出现后的十几年里,在目标识别领域卷积神经网络一直被传统目标识别算法(特征提取+分类器)所压制,直到 ...

  8. 字典序最小是什么意思_《拓扑序简介》第十六讲

    这是民科+大忽悠+地摊报告,我准备把拓扑序吹成天上有地上无.人见人爱.老幼咸宜.不买会后悔的什么东西.珍惜青春,珍惜钱包,请大家谨慎对待大忽悠.下面是回放视频的链接. 蔻享--共享科学.传播科学​ww ...

  9. 推理计算过程_初中物理电学计算题第六讲:极值问题推理和限制条件

    初中物理电学计算题第六讲:极值问题推理和限制条件 前面已经讲过:初中物理电学计算题第三讲:串联电路电流电阻极值推理实例,本讲是这一问题的进一步深入讨论. 题型分析 极值问题是电学计算题中一类较难的题目 ...

  10. java中的多态与继承_【Java学习笔记之十六】浅谈Java中的继承与多态

    1.  什么是继承,继承的特点? 子类继承父类的特征和行为,使得子类具有父类的各种属性和方法.或子类从父类继承方法,使得子类具有父类相同的行为. 特点:在继承关系中,父类更通用.子类更具体.父类具有更 ...

最新文章

  1. 量子计算机就要来了,它真的能改变世界吗?
  2. 留学申请计算机硕士个人陈述,申请美国计算机专业英文个人陈述
  3. CMD(SA400 Command)
  4. kafka channle的应用案例
  5. 5、学MySQL前必须要了解的数据库专业术语
  6. 如何将Git上的项目克隆到idea中
  7. python教程怎么抓起数据_介绍python 数据抓取三种方法
  8. 阿里巴巴产品实习生N天
  9. 数据库:存储过程_数据科学过程:摘要
  10. 实战演示 bacula 软件备份功能
  11. TCP如何利用不可靠的IP协议实现可靠传输
  12. java 3位小数_数字有效小数第三位四舍五入
  13. 关于安卓listview获得item中的控件问题
  14. python的os库_os库(python)—总结
  15. 虚拟化+云服务器,虚拟化+云服务器
  16. vue页面回显数据_解决vue表单回显数据无法修改的问题
  17. acm java题_【转】ACM中java的使用
  18. lambda函数 java_使用 Java 构建 Lambda 函数 - AWS Lambda
  19. 在Java中如何遍历Map对象
  20. c#程序设计实训报告心得体会_c#学习心得体会范文_c#程序设计心得体会

热门文章

  1. 悼念打dota的日子
  2. 和平精英灵敏度分享码服务器没有响应,和平精英灵敏度分享码怎么弄 灵敏度分享码怎么用...
  3. 利用css制作二级下拉菜单
  4. 健身房菜鸟入门小常识
  5. Work breakdown structure 简介
  6. C语言函数定义和函数调用
  7. 1048 习题4-4 三个整数求最大值
  8. [常用类]Instant类的使用
  9. TrustedInstaller
  10. 如何提高国际短信到达率?