Python实战(1)-GUI文本编辑器
创建GUI示例应用程序
为演示Tkinter的用法,我将介绍如何创建一个简单的GUI应用程序。你的任务是编写一个简单的程序,让用户能够编辑文本文件。这里并非要开发功能齐备的文本编辑器,而只想提供基本的功能。毕竟这里的目标是演示基本的Python GUI编程机制。
这个微型文本编辑器的需求如下,
口 让用户能够打开指定的文本文件。
口 让用户能够编辑文本文件。
口 让用户能够保存文本文件。
口 让用户能够退出。
编写GUI程序时,绘制其用户界面草图通常很有帮助。图12-1显示了一个可满足前述文本编辑器需求的简单布局。
这些界面元素的用法如下。
口 在按钮左边的文本框中输入文件名,再单击Open按钮打开这个文件,它包含的文本将出现在底部的文本框中。
口 在底部的大型文本框中,你可随心所欲地编辑文本。
口 要保存所做的修改,可单击Save按钮,这将把大型文本框的内容写入到顶部文本框指定的文件中。
口 没有Quit(退出)按钮,用户只能使用默认Tkinter菜单中的Quit命令来退出程序。
这项任务看起来有点吓人,但其实不过是小菜一碟。
初探
首先,必须导入tkinter。为保留其命名空间,同时减少输入量,可能需要将其重命名
import tkinter as tk
然而,如果你愿意,也可导入这个模块的所有内容。这不会有太大的害处。
>>>from tkinter import *
我们将使用交互式解释器来做些初探工作。要创建GU!,可创建一个将充当主窗口的顶级组件(控件)。为此,可实例化一个Tk对象。
>>> top = Tk()
此时将出现一个窗口。在常规程序中,我们将调用函数mainloop以进入Tkinter主事件循环,而不是直接退出程序。在交互式解释器中,不需要这样做,但你完全可以试一试。
>>>mainloop()
解释器像是挂起了,而GUI还在运行。为了继续,请退出GUI并重启解释器。
有很多可用的控件,它们的名称各异。例如,要创建按钮,可实例化Button类。如果没有Tk实例,创建控件也将实例化Tk,因此可不先实例化Tk,而直接创建控件。
>>>from tkinter import *
>>> btn = Button()
现在这个按钮是不可见的–你需要使用布局管理器(也叫几何体管理器)来告诉Tkinter将它放在什么地方。我们将使用管理器pack–在最简单的情况下只需调用方法pack即可。
>>> btn.pack()
控件包含各种属性,我们可以使用它们来修改控件的外观和行为。可像访问字典项一样访问属性,因此要给按钮指定一些文本,只需使用一条赋值语句即可。
>>btn text’]='Click me!'
至此,应该有一个类似于下面的窗口:
给按钮添加行为也非常简单。
>>>def clicked():
print( I was clicked!)
>>>btn['command']= clicked
现在如果单击这个按钮,将看到指定的消息被打印出来,
可以不分别给属性赋值,而使用方法config同时设置多个属性。
>>> btn.config(text=’Click me!’,
command=clicked)
还可使用控件的构造函数来配置控件。
>>>Button(text='Click me too!', command=clicked).pack()
布局
对控件调用方法pack时,将把控件放在其父控件(主控件)中。要指定主控件,可使用构造函数的第一个可选参数;如果没有指定,将把顶级主窗口用作主控件,如下面的代码片段所示:
Label(text="I’m in the first window!").pack()
second = Toplevel()
Label(second, text="I’'m in the second window!").pack()
Toplevel类表示除主窗口外的另一个顶级窗口,而Label就是文本标签,没有提供任何参数时,pack从窗口顶部开始将控件堆叠成一列,并让它们在窗口中水平居中。例如,下面的代码生成一个又高又窄的窗口,其中包含一列按钮:
for i in range(10):
Button(text=i). pack()
所幸可调整控件的位置和拉伸方式。要指定将控件停靠在哪一条边上,可将参数side设置为LEFT
RIGHT、TOP或BOTTOM。要让控件在x或V方向上填满分配给它的空间,可将参数f设置为X、Y或BOTH。
要让控件随父控件(这里是窗口)一起增大,可将参数expand设置为True。还有其他的选项,如指定锚点和
内边距的选项,但这里不会使用它们。要快速了解可用的选项,可执行如下命令:
>>>help(Pack.config)
还有其他的布局管理器,具体地说是grid和place,它们可能更能满足你的需求。与pack布局管理器样,要使用它们,可对控件调用方法grid和place。为避免麻烦,在一个容器(如窗口)中应只使用一种布局管理器。方法grid让你能够这样排列控件:将它们放在不可见的表格单元格中。为此需要指定参数row和column,还可能要指定参数rowspan或columnspan–如果控件横跨多行或多列。方法place让你能够手工放置控件–通过指定控件的x和y坐标以及高度和宽度来做到。这在大多数情况下都是馊主意,但偶尔可能需要这样做。这两个几何体管理器都还有其他的参数,要详细了解,可使用如下命令
help(Grid.configure)
>>help(Place.config)
事件处理
你知道,可通过设置属性command给按钮指定动作(action)。这是一种特殊的事件处理,但Tkinter还提供了更通用的事件处理机制:方法bind。要让控件对特定的事件进行处理,可对其调用方法bind,并指定事件的名称和要使用的函数。下面是一个示例:
>>>from tkinter import *
>>>top =Tk()
>>> def callback(event):
print(event.x, event.y)
>>>top.bind('<Button-l>’, callback)
4322424456callback
其中是使用鼠标左按钮(按钮1)单击的事件名称。我们将这种事件关联到函数callback。这样,每当用户在窗口top中单击时,都将调用这个函数。向函数callback传递一个event对象,这个对象包含的属性随事件类型而异。例如,对于鼠标单击事件,它提供了x和y坐标,在这个示例中将它们打印出来了。还有很多其他类型的事件,完整的清单可使用下面的命令来获取:
>>> help (Tk. bind)
最终的程序
至此,我们大致具备了编写前述程序所需的知识,但还需获悉用于创建小型文本框和大型文本区域的控件的名称,通过快速浏览文档可知,要创建单行文本框,可使用控件Entry。要创建可滚动的多行文本区域可结合使用控件Text和Scrollbar,但模块tkinter.scrolledtext已经提供了一种实现。要提取Entry控件的内容,可使用其方法get。对于ScrolledText对象,我们将使用其方法delete和insert来删除文本。调用方法delete和insert时,需要使用合适的参数来指定文本的位置;在这里,我们将使用’1.0’来指定第1行的第0个字符(即第一个字符前面),1使用END来指定文本未尾,并使用INSERT来指定当前插入点,最终的程序如代码清单12-1和图12-2所示。
代码清单12-1 简单的GUI文本编辑器
from tkinter import *
from tkinter.scrolledtext import ScrolledText
top = Tk()
top.title("Simple Editor")
contents = ScrolledText()
contents.pack(side = BOTTOM, expand = True, fill = BOTH)
filename = Entry()
filename.pack(side = LEFT, expand = True, fill = X)
def load():
with open(filename.get()) as file:
contents.delete('1. 0', END)
contents.insert(INSERT, file.read())
def save():
with open(filename.get()) as file:
file.write(contents.get('1. 0', END))
Button(text = "open", command = load).pack(side = LEFT)
Button(text = "save", command = save).pack(side = LEFT)
mainloop()
你可按如下步骤来尝试使用这个文本编辑器。
(1)运行这个程序,你将看到一个类似于图12-2的窗口。
(2)在大型文本区域中输入一些内容,如Hello, world!。
(3)在小型文本框中输入一个文件名,如hello.txt。请确保指定的文件不存在,否则原有文件将被覆盖
掉。
(4)单击Save按钮。
(5)退出程序。
(6)再次启动程序。
(7)在小型文本框中输入刚才输入的文件名,
(8)单击Open按钮,这个文件包含的文本将出现在大型文本区域中。
(9)随心所欲地编辑这个文件,再保存它
现在可以不断地打开、编辑并保存,厌烦后就可开始考虑如何改进了。例如,让这个程序使用模块urllib下载文件如何?
当然,还可考虑在程序中采用面向对象程度更高的设计。例如,你可能想自定义一个应用程序类,再通过实例化这个类来创建主应用程序;同时,在这个自定义应用程序类中包含设置各种控件和绑定的方法。与其他GUI包一样,Tkinter也提供了一组卓越的控件和其他类以供使用。对于要使用的图形界面元素,你应使用help(tkinter)或参阅文档以获悉有关它的详细信息。
小结
同样,下面来复习一下介绍的内容。
口 图形用户界面(GUI):GUI有助于让应用程序对用户更友好。并非所有的程序都需要GUI,但只要程
序需要与用户交互,GUI就可能很有帮助。
口 Tkinter:Tkinter是一个跨平台的Python GUl工具包,成熟而且使用广泛。
布局:通过指定组件的几何属性,很容易对其进行定位,但要确保它们在父窗口的大小发生变化时
做出正确的反应,就必须使用布局管理器。
口 事件处理:GUI工具包中用户触发事件执行的操作。要发挥作用,程序可能需要响应某些事件,否则用户将无法与之交互。在Tkinter中,要给组件添加事件处理程序,可使用方法bind。