可爱的 Python:Python 中的 TK编程

给使用 Python GUI 库的初学者的提示

David Mertz 博士

2000 年 12 月 01 日发布

我想要向您介绍能想像到的开始 GUI 编程的最简单方法,就是使用

Scriptics 的 TK 和 Tkinter 封装器。我们将与

developerWorks

中的

“Python 中的 curses

编程” 提到的 curses 库进行很多比较。除了 curses

实现文本控制台而 TK 实现 GUI

这一差别之外,这两个库有着惊人相似的接口。在使用任何一个库之前,需要基本了解窗口和事件循环,并参考可用的窗口小部件。(好,好的参考和适量的练习。)

如同关于 curses 的文章,本文仅讨论 Tkinter 本身的特性。既然很多

Python 发行版都带有 Tkinter,因此可能无需下载支持库或其它 Python

模块。本文后面的

参考资料 指向几个更高级别的用户接口窗口小部件的集合,但是您可以用

Tkinter 本身做许多事,包括构造自己的高级窗口小部件。学习基本

Tkinter 模块将为您引入 TK

的思维方式,即使您继续使用更高级的窗口小部件集合,这种思维方式仍十分重要。

TK

简要描述

TK 是与 TCL 语言关系最密切、且被广泛使用的图形库,TCL 语言和 TK

都由 John Ousterhout 开发。虽然 TK 于 1991 年作为 X11

库出现,但实际上它从那时起就被移植到每一种流行的 GUI。(它与 Python

逐渐拥有“标准”GUI

的情形相似。)现在,大多数流行语言和很多小型语言都有 TK

绑定(Tkinter 模块)。

在开始之前,我必须承认:我不是瘦小枯干的 TK

编程专家。事实上,我的大部分 TK

编程经验大约从我写这篇文章三天前才开始。那三天并非没有挑战,但是最后我觉得很好地掌握了

Tkinter。我在这里要说的是:TK 和 Tkinter

封装器设计得都非常好,便于用户操作,并且只是关于 GUI

编程最简单的介绍。

从测试应用程序开始

我们将使用 Txt2Html,这个在以前很多专栏(请参阅

参考资料 )中使用的文件格式转换程序,的封装器作为测试应用程序。虽然可以用几种方式运行

Txt2Html,但这里的封装器却要从命令行运行

Txt2Html。该应用程序以批处理进程的形式运行,并带有指出要执行的转换各方面特性的命令行自变量。(以后,最好为用户提供交互式选择屏幕选项,以在执行实际转换之前引导用户逐步选择不同的转换选项并提供所选选项的可视反馈。)

tk_txt2html

基于带有下拉菜单和嵌套子菜单的顶部菜单。旁边有详细的实现说明,它看起来与在

“Python 中的 Curses

编程” 中讨论的 curses 版本很相象。虽然 TK

用较少的代码可以实现更多的功能,但很明显,tk_txt2html 和

curses_txt2html 很相似。例如,在 TK

中,象菜单这样的特性可以依靠内置的 Tkinter

类实现,而无需从头编写。

除了设置配置选项之外,TK 封装器还包括一个与 TK Text

窗口小部件一起构建的滚动帮助框(一个带有 Message

窗口小部件的“关于”框)和一个进行 TK

动态几何管理的历史窗口。与大多数交互式应用程序一样,封装器用 TK 的

Entry 窗口小部件接受某些用户输入。

在进一步讨论代码之前,让我们看一下实际运行中的应用程序。

学习基本知识

实际上,Tkinter 程序只需做三件事:

最小的 [Tkinter] 程序import Tkinter # import the Tkinter module

root = Tkinter.Tk() # create a root window

root.mainloop() # create an event loop

这是一个完全有效的 Tkinter 程序(不要介意它没有实际用处,因为它甚至不管理 "hello world")。该程序唯一需要做的是创建一些容纳其根窗口的窗口小部件。这样增强之后,无需程序员进一步干涉,该程序的 root

.mainloop() 方法调用就可以处理所有用户交互。

main()

函数

现在,我们看一下 tk_txt2html.py 更现实的 main()

函数。请注意,我更喜欢使用 John Grayson 的

import

Tkinter 语句,而不是

from Tkinter

import (请参阅

参考资料 中所列的他的书籍)。这不是因为我担心名称空间的干扰(

from ... import 语句的通常警告),而是因为我想明确使用

Tkinter

类;我不想冒险将它们与我自己的函数和类相混淆)。建议您也这样做,至少在开始时这样做。

tk_txt2html main() 函数def main():

global root, history_frame, info_line

root = Tkinter.Tk()

root.title('Txt2Html TK Shell')

init_vars()

#-- Create the menu frame, and menus to the menu frame

menu_frame = Tkinter.Frame(root)

menu_frame.pack(fill=Tkinter.X, side=Tkinter.TOP)

menu_frame.tk_menuBar(file_menu(), action_menu(), help_menu())

#-- Create the history frame (to be filled in during runtime)

history_frame = Tkinter.Frame(root)

history_frame.pack(fill=Tkinter.X, side=Tkinter.BOTTOM, pady=2)

#-- Create the info frame and fill with initial contents

info_frame = Tkinter.Frame(root)

info_frame.pack(fill=Tkinter.X, side=Tkinter.BOTTOM)

# first put the column labels in a sub-frame

LEFT, Label = Tkinter.LEFT, Tkinter.Label # shortcut names

label_line = Tkinter.Frame(info_frame, relief=Tkinter.RAISED, borderwidth=1)

label_line.pack(side=Tkinter.TOP, padx=2, pady=1)

Label(label_line, text="Run #", width=5).pack(side=LEFT)

Label(label_line, text="Source:", width=20).pack(side=LEFT)

Label(label_line, text="Target:", width=20).pack(side=LEFT)

Label(label_line, text="Type:", width=20).pack(side=LEFT)

Label(label_line, text="Proxy Mode:", width=20).pack(side=LEFT)

# then put the "next run" information in a sub-frame

info_line = Tkinter.Frame(info_frame)

info_line.pack(side=Tkinter.TOP, padx=2, pady=1)

update_specs()

#-- Finally, let's actually do all that stuff created above

root.mainloop()

在这个简单的

main() 函数中有几件事要注意:每一个窗口小部件都有一个父代。每当创建窗口小部件时,传递给实例创建的第一个自变量是新的窗口小部件的父代。

如果有其它窗口小部件创建自变量,将通过名称传递它们。Python

的这一特性给我们以指定选项或允许它们取缺省值的极大灵活性。

有几个窗口小部件实例 (Frame)

是全局变量。可以通过在函数间传递变量来使它们成为本地变量,以便维护代码范围的理论纯洁性,但是与它的实际用处相比过于麻烦。另外,使这些基本的

UI

元素全局化强调了这样一个事实:它们可以在整个函数中使用。但是,要确保对自己的全局变量使用良好的命名规范。(事先给您一个警告,Python

人员看起来讨厌匈牙利符号。)

创建完窗口小部件之后,我们调用一个几何图形管理器来让 TK

知道在哪里放置窗口小部件。TK

在计算细节信息时有许多魔力,特别是当调整窗口大小或动态添加窗口小部件时更是如此。但是在任何情况下,都需要让

TK 知道使用哪套咒语。

应用几何图形管理器

TK

提供三个几何图形管理器:

.pack() 、

.grid()

.place() 。虽然

.place()

可用于精细(换句话说,非常复杂)的控制,但 tk_txt2html

只使用头两个。大多数时候,您将使用

.pack() 。

当然,可以不带自变量来调用

.pack()

方法。但是如果那样做,窗口小部件可能会在显示屏幕的某处结束,您可能也想为

.pack() 提供一些提示。这些提示中最重要的是

side 自变量。可能的值是 LEFT、RIGHT、TOP 和

BOTTOM(请注意这些是 Tkinter 名称空间中的变量)。

.pack()

的许多魔力来自可以将窗口小部件嵌套这一事实。特别的,除了作为其它窗口小部件的容器(它有时显示不同类型的边界)之外,Frame

窗口小部件几乎不作什么。这样,就可以很方便地在所希望的方向排列几个框架,然后在每个框架中添加其它窗口小部件。按照调用框架(以及其它窗口小部件)的

.pack()

方法的顺序来排列它们。因此,如果两个窗口小部件都请求

side=TOP ,则满足先进入的请求。

tk_txt2html 还偶尔使用

.grid() 。grid

几何图形管理器用可视的坐标线覆盖父代窗口小部件。当窗口小部件调用

.grid(row=3, column=4)

时,它请求其父代将它放在第三行第四列上。通过查看父代的所有子代的请求来计算父代的总行数和总列数。

别忘了对自己的窗口小部件应用几何图形管理器,以免在显示屏幕上看不到它们时后悔莫及。

菜单

Tkinter

能轻易生成菜单。虽然我们在这里使用十分简单的示例,但是如果愿意,还可以用不同的字体、图形、复选框和各种别致的子代窗口小部件来填充菜单。在我们的示例中,tk_txt2html

的菜单全部用我们在上面所见的行创建。menu_frame.tk_menuBar(file_menu(), action_menu(), help_menu())

这行本身可能有些神秘。大多数必须完成的工作位于名为

*_menu() 的函数中。让我们看一下最简单的示例。

创建下拉菜单def help_menu():

help_btn = Tkinter.Menubutton(menu_frame, text='Help', underline=0)

help_btn.pack(side=Tkinter.LEFT, padx="2m")

help_btn.menu = Tkinter.Menu(help_btn)

help_btn.menu.add_command(label="How To", underline=0, command=HowTo)

help_btn.menu.add_command(label="About", underline=0, command=About)

help_btn['menu'] = help_btn.menu

return help_btn

下拉菜单是将 Menu 小窗口部件作为子代的 Menubutton

小窗口部件。

.pack() (或

.grid() 等)将

Menubutton 排列在适当的位置。Menu 小窗口部件用

.add_command() 方法添加项。(请注意上面为 Menubutton

的目录所作的奇怪分配。不要问为什么,跟着我这样做并在您自己的代码中也这样做即可。)

获得用户输入

下面将看到的示例演示 Label 小窗口部件 widget 如何显示输入(有关

Text 和 Message 小窗口部件的某些示例的完整资源,请参阅

参考资料 )。字段输入的基本小窗口部件是

Entry。它易于使用,但是如果以前曾使用过 Python 的

raw_input() 或 curses 的

.getstr() ,您将发现技巧略有不同。TK 的 Entry

小窗口部件不返回可分配的值。相反,它获取自变量来填充字段对象。例如,下面的函数允许用户指定输入文件。

接受用户字段输入def GetSource():

get_window = Tkinter.Toplevel(root)

get_window.title('Source File?')

Tkinter.Entry(get_window, width=30,

textvariable=source).pack()

Tkinter.Button(get_window, text="Change",

command=lambda: update_specs()).pack()

这里有几件事要注意。我们为这个输入创建了一个新的 Toplevel 小窗口部件和对话框,并且通过创建一个带有

textvariable 自变量的 Entry 小窗口部件指定了输入字段。但是等一下,还有件事!

textvariable

自变量没有指定简单的字符串变量。相反,它引用一个 StringVar

对象。在我们的示例中,从

main() 调用的

init_vars() 函数包含三行。source = Tkinter.StringVar()

source.set('txt2html.txt')

这创建了一个适用于用户输入的对象并为其分配了初始值。每次在与之相链接的 Entry 小窗口部件中进行更改时都立即修改该对象。每次在 Entry 小窗口部件中击键、而不是读取终止时,都进行

raw_input() 样式的更改。

要想获得户输入的值,我们使用 StringVar 实例的

.get() 方法。例如:source_string = source.get()

结束语

此处所略述的技巧以及我们在完整的应用程序源代码中使用的技巧应该足以使您开始进行

Tkinter

编程了。略微实践之后您就会发现它不难掌握。有一个好处是:可以通过

Python 以外的很多语言访问 TK 库,因此您使用 Python 的 Tkinter

模块学到的大多数知识可以应用到其它语言。

相关主题几个

小窗口部件集合 可以节省您构造复杂

UI 的时间。PMW (Python Mega Widgets) 完全用 Python 编写并广泛用于

Python 社区。

Fredrik Lundh 编写了一个比本文包含更多详细信息的 Tkinter

教程。

有几本印刷书籍值得一看。第一本是对 TK

本身所作的很好的介绍。第二本专门讲 Python,并有很多使用 PMW

集合的示例:

TCK/TK in a Nutshell ,Paul Raines 和 Jeff Tranter

著(O'Reilly,1999 年)

Python and Tkinter Programming John E. Grayson

著(Manning,2000 年)

ActiveState 最近创建了一个极佳的

包括

Tkinter 的 Python

发行版 ,以及各种其它大多数其它发行版所没有的其它方便的包和模块。他们还为那些倾向于其它脚本语言的人创建了

ActivePerl 发行版。)

重新命名了

Scriptics (TK

维护者和创始人)。

请阅读

developerWorks 上 David Mertz

撰写的这些相关文章:

python中tk_可爱的 Python:Python 中的 TK编程相关推荐

  1. 使用Python,OpenCV+OCR检测护照图像中的机器可读区域(MRZ Machine-Readable Zones)

    使用Python,OpenCV+OCR检测护照图像中的机器可读区域(MRZ Machine-Readable Zones) 1. 效果图 2. 原理 3. 源码 参考 这篇博客将介绍如何只使用基本的图 ...

  2. python 加载动图_在浏览器中使用TensorFlow.js和Python构建机器学习模型(附代码)...

    大数据文摘授权转载自数据派THU 作者:MOHD SANAD ZAKI RIZVI 本文主要介绍了: TensorFlow.js (deeplearn.js)使我们能够在浏览器中构建机器学习和深度学习 ...

  3. python函数手册68_直接在python中检索68个内置函数?

    Python 3.5中的一种方法是列出具有__module__属性的对象,并将其设置为builtins和lowercase name: >>> sorted(k for k, v i ...

  4. load python txt文件_详解Python中numpy.loadtxt()读取txt文件

    为了方便使用和记忆,有时候我们会把 numpy.loadtxt() 缩写成np.loadtxt() ,本篇文章主要讲解用它来读取txt文件. 读取txt文件我们通常使用 numpy 中的 loadtx ...

  5. 关于python缩进的描述中_关于Python程序中与“缩进”有关的说法中,以下选项中正确的是()...

    关于Python程序中与"缩进"有关的说法中,以下选项中正确的是() 答:缩进在程序中长度统一且强制使用 同文学或同音乐主题的民歌,<_______>是其中之一.此曲经 ...

  6. python post与get的区别_python中get和post有什么区别

    更多编程教程请到:菜鸟教程 https://www.piaodoo.com/ 友情链接: 高州阳光论坛https://www.hnthzk.com/ 人人影视http://www.sfkyty.com ...

  7. python语言中一切皆对象_2 python 中一切皆对象

    python 中一皆对象 在 python 编程语言中所有的一切都是对象 , python 语言相对于 C++ 或 java 这样的语言 (静态语言), 面向对象这个思想更加的彻底. 2.1 函数和类 ...

  8. python使用matplotlib可视化、查看matplotlib中常用的线条形式(line style)和数据点标记形状(marker)

    python使用matplotlib可视化.查看matplotlib中常用的线条形式(line style)和数据点标记形状(marker) 目录

  9. Python可视化(matplotlib)在图像中添加文本和标记(Text and Annotation)

    Python可视化(matplotlib)在图像中添加文本和标记(Text and Annotation) 目录 Python可视化(matplotlib)在图形中添加文本和标记(Text and A ...

最新文章

  1. 干货丨各种机器学习任务的顶级结果(论文)汇总
  2. 机器学习之sklearn——聚类
  3. wpf怎么让grid表格中元素显示到最顶层_一文搞定PPT中的快捷键
  4. C4C里产品主数据和销售组织数据维护的相互作用和相互影响
  5. php自动维护,window_Win7系统中的一些自动维护计划、任务关闭、禁用方法图文教程,  windows自动维护功能会在计 - phpStudy...
  6. cookie与token对比(转)
  7. 那些在错误道路上一路狂奔的国产VR
  8. springboot异常处理机制之统一异常处理和自定义异常类
  9. Caffe模型详细介绍
  10. instantclient_11_2远程连接Oracle安装,绝对清晰易懂
  11. 电子计算机和量子力学,通俗讲解一下量子计算机究竟是怎么运作的?其实量子力学并不深奥...
  12. 设备报废鉴定怎么做?
  13. Ajax上传文件(视频),并获取上传进度、上传速度和剩余时间。
  14. Android 12.0 修改系统默认字体的大小
  15. MySQL入门学习的第一节(SQL语句)
  16. Cadence教程4——环形振荡器
  17. 结对作业 微软学术搜索分析
  18. 晨哥真有料丨 “不断提升自己,有择偶标准” 的男生会被倒追
  19. 2021年裂解(裂化)工艺复审模拟考试及裂解(裂化)工艺作业模拟考试
  20. Unable to paint on Qt Widget, shows error “paintEngine: Should no longer be called”

热门文章

  1. 自动化测试库、框架和工具之间的区别
  2. python数据挖掘例题_大工20春《数据挖掘》在线作业1题目【标准答案】
  3. matlab电气仿真模块b25,基于Matlab的由双馈风力发电机组成的风电场仿真
  4. 实现一个 Spring Boot Starter 原来如此简单,读 Starter 源码也不在话下
  5. 基于物联网的环境调节系统(ESP32-C3+Onenet+微信小程序)
  6. 【博学谷学习记录】超强总结,用心分享| jQuery简介
  7. GEE实战 | LULC获取与处理
  8. ROS环境下大疆tello无人机源码安装驱动代码解读
  9. CS5266设计Typec转HDMI+PD+U2+U3四合一多功能拓展坞方案
  10. 【Linux】环境变量和命令行参数