简单介绍利用TK在Python下进行GUI编程的教程

发表于 5年以前  | 总阅读数:373 次

我想要向您介绍能想像到的开始 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 窗口小部件接受某些用户输入。

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

201541390858446.gif \(565×236\)

学习基本知识

实际上,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 模块学到的大多数知识可以应用到其它语言。

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237269次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8108次阅读
 目录