课后习题

第11章 图形用户界面

问题导向

·如何将用户与计算机的交互以图形用户界面的形式呈现?

·图形用户界面的各种元素怎么创建?

·多种图形用户界面元素怎么布局?

·界面操作如何与后台数据关联?

重点与难点

·图形用户界面的基本操作。

·tkinter模块中基本组件的使用方法。

·tkinter子模块下的组件使用方法。

·应用图形用户界面进行系统设计。

知识导图

Python之旅——旅行导航

到一个陌生的城市旅行,如何快速地找到去往景点的路径?当然是开启智能时代产品地图导航。在Python中也可以实现这种看得到的功能效果,采用的是图形用户界面的方法,用看得见的图形来引导用户解锁产品。在这一站,我们通过图形用户界面的方法来实现按图导航,体验旅行之乐。

图形用户界面(Graphical User Interface,GUI)又称为图形用户接口,它是一套工具集,可以结合各种计算机语言进行界面开发。

在主流计算机环境中有3种软件操作界面:一是以DOS为代表的二维界面,以命令符方式进行交互;二是以Windows为代表的三维图形化用户界面,以各类窗口与按钮等元素进行交互;三是以网页为代表的Web用户界面。

Python作为一门优秀的语言,自诞生之日起,已经结合了许多优秀的GUI工具集,人们通过它编写了许多的应用程序。Python提供了多种图形开发界面的库,几个常用Python GUI库如下。

·tkinter:tkinter模块(Tk接口)是Python标准Tk GUI工具包的接口,Tk和tkinter可以在大多数UNIX平台下使用,同样可以应用在Windows和macOS系统里。Tk 8.0的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。

·wxPython:wxPython是一款开源软件,是Python语言一套优秀的GUI图形库,可使Python程序员很方便地创建完整的、功能健全的GUI用户界面。

·PyQt:PyQt是Qt公司Qt应用程序框架的一组Python V2和V3的绑定,可以在Qt支持的所有平台上运行,包括Windows、macOS、Linux和Adroid,部分免费。

·Jython:Jython程序可以和Java无缝集成。除了一些标准模块,Jython还使用Java的模块。Jython几乎拥有标准的Python中不依赖C语言的全部模块。比如,Jython的图形用户界面使用Swing、AWT或者SWT。Jython可以被动态或静态地编译成Java字节码。

这一章主要向大家介绍tkinter的使用。需要说明的是,tkinter虽然很好用,但是它提供的功能还是太少了,许多功能需要开发者自己去实现。wxPython、PyQt这些第三方库各有自己的优势,大家可以在实际的GUI编程中,选择适合自己的工具包。

11.1 tkinter概述

tkinter基于的Tk技术最初是为TCL语言设计的。由于Tk技术非常灵活,所以其很快被应用在很多计算机语言中,包括Python(tkinter)、Perl(Perl/Tk)、Tuby(Ruby/Tk)等。

tkinter是Python默认的GUI库,Python使用tkinter可以快速地创建GUI应用程序。相对于其他Python GUI库,tkinter简单易学,可以使用少量的代码编写功能强大的GUI。tkinter内置在Python的安装包中,只要安装好Python,就能通过import tkinter导入库直接使用。下面两种导入方法都可用。

方法一:

方法二:

11.1.1 tkinter窗体

1.创建

图形用户界面程序都需要一个根窗口,也称为主窗口。图形用户界面的主窗口就像在绘画时需要的画纸一样。主窗口是图形用户界面各种组件的载体,一个应用程序只能有一个主窗口。Tk类提供了创建主窗口的构造函数,方法如下:

2.窗体属性与方法

如果想要在创建窗口时对窗口的大小进行设置,则可以调用窗口对象的方法geometry()。geometry()方法需要传入一个字符串,如要设置窗口宽为100像素,高为50像素,形成一个长方形的窗口,写法是geometry()。

还可以通过title()方法为窗口设置标题,如title("图形用户窗口")。

如果还要设置特有的窗体图标,则可使用iconbitmap(),如iconbitmap('exampl/Tool.ick')。

窗体的背景颜色可以通过背景属性进行修改,格式为:

创建窗口后,要让窗口运行并能及时响应用户交互操作,需要不断检测事件,刷新组件,用到方法mainloop()。mainloop()用来启动窗体事件循环,并等待接收各种事件信息,不停地告诉GM(Geometry Manager)有一个组件产生。

例如,创建一个200×100大小的窗体并运行,代码如下:

运行结果如图11-1所示。

图11-1 创建窗口

11.1.2 tkinter组件

Python中tkinter的组件主要存放在tkinter、tkinterr.ttk、tkinter.tix、tkinter.scrolledtext模块中。

1.常用组件

tkinter提供了非常多的组件,表11-1列出了使用频率较高的19个组件。

表11-1 tkinter中使用频率较高的19个组件

例如,在窗口上添加一个按钮组件的代码如下:

运行结果如图11-2所示。

2.组件标准属性

标准属性是所有组件共有的属性,如大小、颜色等。具体属性如表11-2所示。

图11-2 添加按钮组件

表11-2 组件标准属性

例如,在窗口中设置按钮与标签,代码如下:

运行结果如图11-3所示。

组件的属性设置有3种方式。

①在创建组件对象时,使用构造函数来创建组件并设置属性,如:

在创建按钮对象时,给它设置文本属性和宽度属性。

图11-3 组件显示

②在组件创建后,使用字典索引的方式设置属性值,如:

通过字典索引的方式将按钮上的文本设置为蓝色。

③使用config()方法更新多个属性对象,如:

同时设置按钮上文本的颜色以及按钮的背景色。

11.1.3 tkinter组件布局

tkinter支持3种几何布局管理器,分别是pack、grid、place。它们主要决定组件的排列位置。不管哪一种几何布局管理器,在同一个父窗口中,都不可以混合使用。

1.pack(parameter)几何布局管理器

pack()可以使组件定位到窗体或其他组件指定的位置,parameter为pack()的可选参数,常用可选项有如下几个。

①side:决定组件的排列方式,默认值为side="top",表示在顶端放置组件。还可以显式设置为buttom(在下端)、left(在左端)、right(在右端)。pack()省略参数时表示side="top"。

②padx、pady:可以指定组件之间x、y方向上间隔的大小,默认单位为像素,也可设置成单位c(厘米)、m(毫米)、i(英寸,1英寸=2.54 cm)、p(打印机的点,即1/27英寸),如pack(padx=20,pady="3m")。

③anchor:组件之间的对齐方式,值可设置为w(左对齐/靠西方向)、e(右对齐/靠东方向)、n(顶对齐/靠北方向)、s(底对齐/靠南方向)、nw(左上对齐/靠西北方向)、sw(左下对齐/靠西南方向)、se(右下对齐/靠东南方向)、ne(右上对齐/靠东北方向)、center(中间对齐)。默认是center。

2.grid()几何布局管理器

grid()几何布局管理器是指将组件放置在一个二维的表格里,主组件被分割成一系列的行与列,表格中的单元格都可以放置组件。grid()的参数如表11-3所示。

表11-3 grid()的参数

在组件外部,左右方向各填充指定长度的空间。

如果没有声明sticky属性,默认将插件居中于单元中。

通过设置sticky=tk.E(靠右上方),sticky=tk.SE(靠右下方),sticky=-th.SW(靠左下方),sticky=tk.NW(靠左上方),可以将插件布置在单元的某个角落。

通过设置sticky=tk.W(靠上方),sticky=tk.E(靠右方),sticky=tk.S(靠下方),sticky=th.W(靠左方),可以将插件布置在单元的某个方向上。

通过设置sticky=tk.N+tl.S,在垂直方向上延伸插件,并保持水平居中。

通过设置sticky=tk.E+tk.W,在水平方向上延伸插件,并保持垂直居中。

通过设置sticky=tk.N+th.E+tk.W,在水平和垂直方向上延伸插件,填满单元。

也可以使用其他的组合。比如,sticky=tk.N+tk.S+tk.W,在垂直方向上延伸插件,并靠左布放。

通过一个表格来理解grid()布局,具体布置如图11-4所示。

图11-4 布局格式效果

用grid()几何布局管理器将整个窗体分成四行三列,包含7个组件。

·label1在第0行、第0列,跨三列显示。

·label2在第1行、第0列,左右两侧间距40像素。

·entry1在第1行、第1列。

·label3在第2行、第0列,左右两侧间距40像素,上下间距20像素。

·entry2在第2行、第1列。

·label4在第1行、第2列,跨两行显示,左右两侧间距10像素。

·button1在第3行、第1列,跨两列显示。

实现图11-4布局的代码如下:

运行效果如图11-5所示。

图11-5 grid()布局效果

3.place()几何布局管理器

place()几何布局管理器可以指定组件放在一个特定的位置,它分为绝对布局和相对布局。place()常用属性如表11-4所示。

表11-4 place()常用属性

relx、rely在相对布局时使用,relx=0,rely=0的位置是左上角,relx=0.5,rely=-0.5的位置是屏幕中心。

使用place()几何布局管理器实现图11-5所示效果的代码如下:

11.2 tkinter事件

11.2.1 tkinter事件类型

事件就是触发的一些动作,如单击菜单、单击鼠标等。根据不同的动作,想要让程序执行不同的功能,就需要对事件进行处理,也就是调用不同的函数来完成相应的功能。

tkinter中的事件都是用字符串来描述的,基本格式是:

其中modifier和detail可以提供一些附加信息,modifier为组合键的定义,例如,同时按下Ctrl键;detail用于具体信息,如按下键盘中B键;type指的是事件的类型。type为通用类型,例如键盘按键(KeyPress)。

type指的是事件的类型。常见的事件类型如表11-5所示。

表11-5 常见的事件类型

常见的<modifier-type-detail>格式组合的常用事件类型如下。

(1)鼠标单击事件

<Button-1>:单击鼠标左键。

<Button-2>:单击鼠标中间键(如果有)。

<Button-3>:单击鼠标右键。

<Button-4>:向上滚动滑轮。

<Button-5>:向下滚动滑轮。

(2)鼠标双击事件

<Double-Button-1>:鼠标左键双击。

<Double-Button-2>:鼠标中键双击。

<Double-Button-3>.:鼠标右键双击。

(3)鼠标释放事件

<ButtonRelease-1>:鼠标左键释放。

<ButtonRelease-2>:鼠标中键释放。

<ButtonRelease-3>:鼠标右键释放。

(4)鼠标按下并移动事件(即拖动)

<B1-Motion>:左键拖动。

<B2-Motion>:中键拖动。

<B3-Motion>:右键拖动。

(5)鼠标其他操作<Enter>:鼠标进入控件(放到控件上面)

<FocusIn>:控件获得焦点。

<Leave>:鼠标移出控件。

<FocusOut>:控件失去焦点。

(6)键盘按下事件

<Key>:键盘按下,事件Event中的keycode、char都可以获取按下的键值。

<Return>:键位绑定,回车键,其他还有<BackSpace>、<Escape>、<Left>、<Up>、<Right>、<Down>等。

(7)控件属性改变事件<Configure>

控件大小改变,新的控件大小会存储在事件Event对象的width和height属性中,部分平台上该事件也代表控件位置改变。

(8)组合事件

例如<Control-Shift-Alt-KeyPress-A>,表示同时按下Ctrl+Shift+Alt+A 4个键;<KeyPress-A>表示按下键盘中的A键。

11.2.2 事件对象及属性

事件对象是一个标准的Python对象类,拥有大量的属性,用于描述事件。事件对象的常用属性如表11-6所示。

表11-6 事件对象的常用属性

11.2.3 tkinter事件绑定

将组件与事件关联起来就是事件绑定。在Python中,tkinter允许将事件绑定在组件上,格式如下:

widget表示组件,bind()方法将指定的事件绑定到组件上,event参数接收要绑定的事件,handler表示处理事件的函数。

当被触发的事件满足该组件绑定的事件时,tkinter就会带着事件对象(Event)去调用handler()方法。

例如,想要获取鼠标在窗口上单击时的坐标,则可将事件<ButtonRelease-1>与窗体绑定,再设置一个函数,用于处理鼠标单击事件。实现代码如下:

运行结果:

如果希望将一个事件绑定到程序所有的组件上,则可以使用bind_all()函数,格式如下:

【案例11-1】 剪刀石头布游戏。

剪刀石头布游戏是日常生活中常见的一种猜拳游戏,又称为“猜丁壳”,古老而简单,这个游戏的主要目的是解决争议,因为三者相互制约,因此无论平局几次,总会有胜负的时候。在游戏规则中,石头克剪刀,剪刀克布,布克石头。现在设计一个图形化界面的猜拳游戏,实现玩家与计算机比拼,五局三胜,得出最后比分。

案例分析:

游戏可分为3个模块。

·窗口布局:创建窗口,显示字符串变量以及各种在方法中要用到的其他变量。将3张出拳的图片存为一个列表,以便后续选取。

·布局设置:在窗口上显示标签、比分、图片按钮。按钮上的图片即剪刀、石头、布。玩家方用3个按钮显示,以便玩家选择,当玩家单击相应图片时,调用判断方法,并传递选项值过去。计算机方只显示一个按钮,图片从3张图片中随机显示。

·结果判断:当玩家单击按钮选项时调用,接收玩家传递过来的选择值,将该值与计算机中随机生成的值进行对比,判断是玩家赢,则玩家积分加1,计算机赢,则计算机积分加1,平局则两方积分都加1。累计判断次数,当次数为5时,给出最后胜负判断结果,并弹出对话框询问是否重玩游戏,或是退出游戏。

实现代码如下:

运行结果如图11-6所示。

图11-6 游戏运行效果

11.3 tkinter实践应用

【案例11-2】 背单词系统。

实践目的:

·熟悉并掌握软件开发的基本方法及流程;

·熟悉并掌握Python面向对象特性及其在项目中的使用;

·熟悉并掌握图形用户界面的设计与应用;

·熟悉应用系统设计的分层体系架构。

11.3.1 需求分析

1.tkinter功能需求

设计单词练习系统,建立一个单词库,可以从单词库中随机抽取单词进行练习。练习方式有英译中、中译英、拼写填空,对于显示出来的单词可单击声音按钮,系统给出读音。练习时,对于回答正确的会给出提示,并增加积分,错误的只有提示,不加积分。练习完成后可以查看出错的单词,并对错误的单词进行次数统计。

对单词库的单词也能进行查看、增加、删除、修改等操作。

2.tkinter组件需求

涉及的tkinter组件如下。

·变量:在其他组件中要显示的变量需要先声明,如tkinter.StringVar()。

·标签:tkinter.Label(self.wt,text='英文',font=('宋体',12),bg='yellow')。

·文本框:tkinter.Entry(self.root,width=15,font=('宋体',20))。

·按钮:tkinter.Button(self.root,text='查看错词表',width=10,font=('宋体',15),command=self.wrong_word)。

·单选按钮:先创建一个组,再创建单选按钮,将属性variable设置为组名,则可实现一组单选按钮的设计。如:

·表格:先创建表格组件,再设置列属性column的列名称,可设置每一列的列宽,不设置

则会自动按窗口宽度平分各列。表格标题可用heading属性进行设置。

将内容加入表格,使用insert()方法。响应鼠标单击事件可用bind()方法。获取表格中选中内容可用item()方法:

获取表格内容:

表格单击事件:

'<Button-1>':按下左键。

'<ButtonRelease>':按下后松开左键。

3.需要的标准库

涉及的标准库先用import方式导入头部,代码如下:

11.3.2 模块设计

1.模块划分

将整个单词系统划分成以下几个模块。

(1)登录

登录模块包含两种登录方式,一种是用已存在账户登录,另一种是以游客身份登录。

(2)界面设计

界面设计即设计各个模块需要用到的图形化界面,以及各种元素的排版布局。

·登录:用户登录输入信息界面。

·单词练习:积分显示、练习选择、单词显示、单词输入框、提交按钮、链接按钮、读音按钮等。

·错词查看:表格控件、链接按钮。

·排行榜:表格控件、链接按钮。

·单词汇总:表格控件、链接及操作按钮、中英文输入框。

(3)单词练习

显示练习积分,提供练习选项,输入相应中英文,提交输入信息,判断输入信息,实现单词读音语音播放,进入其他界面的按钮功能实现。

(4)错词查看

将练习出错的单词显示出来,并统计显示出错次数。

(5)单词汇总

显示所有单词,并能对单词进行增、删、改、查等操作。

(6)排行榜

显示用户名、积分,以及排名信息。

具体模块划分如图11-7所示。

图11-7 背单词模块划分

2.设计流程

背单词设计流程如图11-8所示。

图11-8 背单词设计流程

11.3.3 模块实现

使用tkinter进行GUI设计,界面可参考图11-9。

图11-9 主界面

1.登录设计

创建登录界面,在初始化方法中构建好登录界面,通过按钮实现页面跳转。登录界面如图11-10所示。

图11-10 登录界面

在登录模块,首先要创建窗口,在窗口中放置如图11-7所示的组件:3个标签、2个文本输入框、2个按钮。其中密码输入框中需要设置密码不可见,可通过将show属性设为“*”实现。两个按钮需要实现界面的跳转与链接交互,可通过设置command属性实现。

当用户输入账号和密码通过按钮提交请求时,需要将接收到的输入信息与文件中存储的用户信息进行匹配。设置一个方法专门从文件中获取用户账号信息,将获取到的信息存储到列表中。

再通过一个方法来判断输入内容与列表中的用户信息是否一致,一致则跳转页面并传递用户信息过去,不一致则弹出对话框。

2.主界面设计

(1)构造方法

在主界面设计中,将背单词系统设计成一个类,在类的构造方法中先将前一个窗口,即登录界面的窗口关闭,再创建主界面窗口。在构造方法中,设置各种初始化变量和方法调用。具体步骤如下。

a)关闭登录窗口,可用destroy()方法实现。

b)创建tkinter窗口对象作为主界面窗口,并设置窗口的相关属性,如大小、标题、背景等。

c)设置窗口中需要使用并能自动刷新的字符串变量tkinter.StringVar,如积分、用户名、显示的随机单词、回答提示信息等。

d)用字符串变量.set()方法设置字符串初始显示值。

e)设置各方法模块需要使用的属性,如单词列表变量、错词列表变量、计分、拼写填空变量等。设置为对象属性,则所有类中所有的方法均可访问。

f)创建单选按钮组号,用tkinter.IntVar()实现。

g)创建随机数,数值用来表示单词表的索引号,用于从单词表中随机抽取单词。

h)调用各种方法,如界面设置布局、窗体运行方法等。

(2)单词读取

从单词库文件中将单词读取出来。单词可以用文件存储,也可以用数据库存储。此处用的是文本文件。文件中一行为一个单词的中英文。

打开文件读取数据,先对数据进行清洗,按换行符将它们分离成列表,一个单词为一个元素。再对列表进行遍历,对于遍历到的每一个元素(即单词)再次进行分离,即每个单词分成中文和英文两个元素,将分离得到的列表追加到初始化设置中创建的单词列表变量中。

实现代码如下:

(3)主界面布局

主界面布局如图11-11所示。

参照主界面图进行界面元素的创建与布局。

a)标题:为标签,放置到顶部。

b)积分:用户名标签+积分标签,用户名标签中的文本属性为“用户名+当前积分”,积分标签中的内容为文本变量,显示为初始设置中的积分变量。

c)单词显示:标签,文本为初始设置中的显示单词变量。

图11-11 主界面布局

d)答案输入:输入文本框。

e)练习方式:单选按钮组,根据选择通过command属性调用不同的方法。

f)回答提示:标签,文本为初始设置中的提示变量。

g)判断(确定):按钮,通过command属性调用判断方法。

h)退出:按钮,通过command属性调用退出方法。

i)查看错词表:按钮,通过command属性调用错词显示方法。

j)查看单词表:按钮,通过command属性调用单词显示方法。

k)查看排行榜:按钮,通过command属性调用排行信息显示方法。

l)读音:按钮,背景图,通过command属性调用读音方法。

布局代码如下:

(4)单词练习方式模块

3个单选按钮对应不同的练习方式。根据选择不同的单选按钮,标签显示不同的内容。练习用户根据标签显示的内容在文本输入框中输入单词对应的中英文,单击“确定”按钮调用相应方法进行判断。方法的调用由各单选按钮的command属性触发,将command属性链接到对应的处理方法中。

单击英译中:标签显示英文,随机显示单词表中的一个单词,同时传递单词的英文给朗读变量。

单击中译英:随机显示单词表中的一个单词,标签显示中文,传递单词的英文给朗读变量。

单击拼写填空:单词字母随机缺少一个。利用随机数函数生成一个数字,遍历英文单词的字母,数字对应的位置替换为下划线,其他的字母正常显示,传递单词的英文给朗读变量。

(5)正误判断

先判断练习方式是哪一种,再获取文本框输入的内容,将获取内容与对应的单词表内容进行比对,相同,则增加积分,给出赞扬提示;不同,则给出鼓励提示,将对应单词加到错词表。

若为拼写填空模式,判断过程如下。

a)获取文本框输入内容(不区分大小写,则统一变成小写)。

b)如果输入内容与空缺内容相同,则给出赞扬提示,增加积分,并将积分变量进行更新,显示在标签中。

c)如果输入内容与空缺内容不同,则给出鼓励提示,将单词追加到错词列表。

d)再次生成随机数,用于下一轮的单词抽取。

e)调用拼写填空方法。

f)将文本输入框的内容清空。

若为中译英或英译中,判断过程如下。

a)如果为中译英模式,设c=1,即与文本框内容进行匹配的是列表中的索引号为1的元素,提取单词中的中文。

b)如果为中译英模式,设c=0,即与文本框内容进行匹配的是列表中的索引号为0的元素,提取单词中的英文。

c)将文本框内容与提取到的内容进行匹配。

d)如果相同,则给出赞扬提示,增加积分,更新积分显示。

e)如果不同,则给出鼓励提示,将单词追加到错词表。

f)再次生成随机数,用于下一轮单词抽取。

g)将抽取到的单词更新并显示出来。

h)清空文本框中的内容。

如果想在输入内容之后按键盘的回车键响应,即按回车键时调用judge()方法,可用如下代码实现:

(6)退出

单击退出按钮,退出程序,实现代码如下:

(7)单词读音

当单击界面上的读按钮时,能对界面上显示的单词进行语音朗读,具体操作如下。

①导入声音库,import win32com.client。

②传递单词的英文部分给Speak()方法,实现单词的朗读。

实现代码如下:

3.错词表

单击“查看错词表”按钮调用wrong_word)方法,则会打开新的窗口,进入错词表界面,原窗口隐藏。在新窗口将错词表中的内容以表格的形式列出来,并显示错误次数。

具体设计步骤如下。

①隐藏原窗口,创建新窗口。

②显示标题:标签。

③创建表格:表格位置、列数目3、列标题。

④遍历错词表,统计错词出现的次数:

a)对错词表进行排序,让相同的单词相邻;

b)在错词表末尾追加一个符号,用于遍历结束,便于统计次数;

c)获取错词中的第一个单词,并设出现次数为1;

d)从第二个单词开始对单词表进行遍历;

e)如果单词跟第一个单词相同,则将次数加1;

f)如果不同,则将单词的英文与中文、次数写入表格中显示,同时将次数修改为1,第一个单词的变量值改为当前单词;

g)将添加的符号删除,以防止下次对它进行统计。

⑤返回主界面:单击返回按钮,返回主界面,设置command事件为back()方法,即可返回主界面。

实现代码如下:

返回按钮的功能:关闭(销毁前一个),使用destroy()方法;同时更新、显示原隐藏主界面,使用update()和deiconify()来实现。

运行效果如图11-12所示。

图11-12 错词表

如果想要通过单击表格的标题对错词表进行排序,如单击标题错误次数,可以按次数降序或升序排序,如图11-13所示。

图11-13 错词表排序

需要先创建列表,对表格中获取的数据进行遍历,存放到创建的列表中,然后对列表进行排序,再对排序过后的列表进行索引移动,实现按所单击的标题进行排序并显示。实现代码如下:

4.单词表显示

在主界面单击“查看单词表”按钮,调用单词表显示方法,会打开新的窗口,并将原窗口隐藏。在新窗口将单词表中的内容以表格的形式列出来,并提供添加、删除、返回按钮,单击按钮调用相关方法。具体过程如下。

①隐藏原窗口,创建新窗口,用Toplevel()方法创建。

②显示标题:标签。

③创建表格:表格位置、列数目2、列标题。

④创建两个文本框,分别用于输入单词的中文和英文。

⑤创建4个按钮,分别对应添加、修改、删除、返回4个功能。

⑥遍历单词表,将单词的英文、中文显示在窗口的表格中。

⑦调用表格组件的左键单击响应事件,当单击表格中某个单词时,对应的中英文会显示在文本输入框中,可对其进行修改。

注意:使用tk.Tk()方法来新建窗口,这样得到的是一个新的根窗口,无法与原来的根窗口进行有效交互。

因此需要使用Toplevel组件新建顶级窗口,Toplevel组件是一个独立的顶级窗口,这种窗口通常拥有标题栏、边框等部件,和Tk()创建出来的根窗口是一样的,共享着一样的方法。

具体代码如下:

运行效果如图11-14所示。

5.单击事件

要实现用鼠标单击单词,被单击单词的中英文出现在界面的中英文输入框中,如图11-15所示,单击单词advise,在英文和中文的文本输入框中自动出现相应的英文和中文。

图11-14 单词表

图11-15 单击事件效果图

定义响应单击事件时,需要传递事件参数event。具体的操作如下。

a)获取列:使用identify_column(event.x)。

b)获取行:使用identify_row(event.y)。

c)将行或行中的元素信息获取到,可使用item(行\列,"values")方法,此处需要获取的是行中的信息。

d)将行中的第一个元素设为文本框中的英文部分并显示(以便单击修改、删除时传递数据)。

e)将行中的第二个元素显示为文本框中的中文部分。

实现代码如下:

接下来定义单击各按钮时响应的事件。

单击“添加单词”按钮实现以下操作:

①获取文本框中输入的单词中文和英文;

②将中英文组合成一个列表,即一个单词;

③判断这个单词是否已在单词表中,如果已存在,则给出提示信息;

④如果不存在,则将它追加到单词表中,显示在窗口表格的末尾。

具体代码如下:

单击“删除”按钮时,从单词列表及显示窗口将单词删除。具体操作如下。

①先弹出警告框,让用户选择是否确定删除单词。

②如果确定删除,将单词从单词表中删除,也从窗口表格中删除,同时弹出删除成功的提示窗口。

实现代码如下:

单击“修改”按钮时,可以对指定单词进行修改。具体操作如下。

①获取文本框中输入的英文和中文。

②弹出警告框,让用户选择是否确定修改单词。

③如果确定修改,则查看输入的英文和中文是否与原单词相同。

④如果相同,则弹出提示窗口。

⑤如果不同,但是输入的英文或中文为空,也弹出提示窗口。

⑥否则就将输入的单词替换为原单词表中的单词,并在窗口的表格中进行更新,给出修改成功的弹出窗口。

实现代码如下:

单击“保存”按钮时,将修改过的单词信息保存到单词文件中。具体操作如下。

①打开文件,以覆盖写的方式打开。

②遍历单词列表,逐行写入单词信息。

③关闭文件。

代码如下:

6.排行榜

在排行榜中,利用表格控件显示所有用户的积分,以及排名信息。

首先要获取排名文件中的排名信息。具体操作如下。

①创建列表,用来存储用户的积分信息。

②打开文件,将文件中的用户积分信息读取出来。需要对读取到的信息进行清理,去掉换行符,按逗号分离用户名和积分。

实现代码如下:

创建排行榜窗口,用列表控件显示排名信息。具体操作如下。

①隐藏主界面窗口,创建新窗口,设置窗口属性。

②设置标签,用来显示“排行榜”标题信息。

③设置表格控件,用3列来分别显示用户名、积分、排名,并将表格绑定单击事件,实现单击表头可进行按表标题排序。

④遍历用户积分列表,如果用户名在列表中存在,则用本次练习的积分替换原有积分。

⑤不存在,则将新用户的信息及积分添加到列表中。

⑥对列表按积分进行降序排序。

⑦遍历排序之后的列表,将信息显示在表格控件中。

实现代码如下:

运行效果如图11-16所示。

图11-16 排行榜

课后习题

1.设计一个图形用户界面的学生成绩管理系统。

2.设计一个界面化的小学生四则运算练习系统。具体要求如下。

用户可以从菜单中选择某种运算进行练习;每次练习10道题;选择某项练习,完毕后给出做对的题数,每小题练习后直接给出是否正确的提示;用户可以反复选择练习,直到选退出为止。由于是小学生,所以程序不能产生诸如不够减的减法、不能整除的除法、分母为0的除法等题目。

(1)功能:执行一道题的练习,并计分。

(2)输入:用户的选择(0——退出,1——加法,2——减法,3——乘法,4——除法)。

(3)返回值:本道题的得分(做对得10分,做错得0分)。

(4)模块内部逻辑:

①随机产生两个操作数;

②产生题目;

③接收用户的输入答案;

④判断正确与否,计分;

⑤退出时给出再见信息。

注意:分母不能为0,被减数要大于减数,被除数必须是除数的整数倍。