Python GUI 编程:wxPython 与 tkinter

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

尽管名为 tkinter 的基于 Tcl/Tk 的 UI 模块是 Python 发行版的一个相当标准的部分,并且已经存在了很长时间,但它经常被从其他方向转向 Python 的开发人员忽略。

我自己的背景主要是在 C/C++ 领域,我对 Qt 和 wxWidgets 有很深的经验。当我十年前开始使用 Python 时,这让我自然而然地专注于 wxPython。我知道 tkinter 存在,但没有太在意。

我认为 Tcl/Tk 是古老的、奇怪的和晦涩的,事实证明这不是我做过的最好的技术判断。

在现代 Tcl/Tk 中,tkinter 简单、强大且快速。它看起来也很不错。 Modern Tk 包含一个通过主题小部件的样式机制,可以让它变得更漂亮。

比较 wxPython 和 tkinter

使用基本示例比较 wxPython 和 tkinter,我们可以了解它们在代码和屏幕上的外观。我并不是要打击 wxPython,它功能强大,文档齐全,多年来一直是我首选的 Python UI 解决方案。但是 tkinter 有一些我非常喜欢的特性,尤其是它处理布局管理的方式。

下面是两个类似示例的屏幕截图,一个使用 tkinter(取自: http ://www.tkdocs.com/tutorial/grid.html),一个使用 wxPython(略微修改自: http://zetcode.com/wxpython/布局/ ):

它们具有可比较的控件和布局。 wxPython版本是76行,tkinter版本是48行,大部分都是布局代码占的。

wxPython 示例使用嵌套的 HBOX 和 VBOX sizer,这是我使用该工具包处理布局的首选方式,因为我发现它更容易推理,因此更容易维护和修改。 tkinter 示例使用网格布局,这确实解释了程序长度的一些差异。然而,它也指出了两个工具包之间完全不同的设计选择:wxPython 在其 sizer 层次结构中将布局类外部化,而 tkinter 将布局内部化,以便每个小部件使用各种策略管理自己的子部件,其中网格只是其中之一.

wxPython 中的 UI 布局不是很有趣,而且我从来没有发现 GUI 构建器——从 DialogBlocks 到 BoaConstructor 等等——有很大帮助。管理 sizer 和窗口的并行层次结构增加了复杂性,而没有很多附加功能 - 以 1990 年代那种令人愉快的面向对象的方式,这在当时对我们所有人来说都是一个好主意。

tkinter 通过将布局策略隐藏在小部件界面后面来消除所有这些。您只需将孩子添加到他们父母的网格中。您不必创建 grid sizer,将子级添加到其中,然后将其设置为父级的 sizer。这不可避免地会创建一堆名称,例如“gridSizer1”,当您需要编辑 UI 代码时,您会后悔的。

然后是速度对比。例如,从在命令提示符下键入 python myapp.py 到屏幕上显示 UI 需要多长时间?在台式机上差异可以忽略不计,但在小型嵌入式 ARM 处理器上,这些简单示例程序的挂钟秒数如下所示:

wxPython:6 秒

tkinter:1 秒

这不是世界上最复杂的测试——我只是用我的手表计时——但差异如此之大,不必如此。用户愿意接受的规范绝对响应时间是 2 秒,从三倍到不到一半是一个大问题。

这些年我做了很多嵌入式的工作,甚至把wxX11编译到一个计算能力几乎和烤面包机一样的ARM板子上。 C++ 版本速度足够快,用户不会体验到可察觉的延迟。我在同一个系统上运行了一些基于 wxPython 的工具(现场工程师的维护脚本,他们会容忍任何事情)并且总是对它们的速度感到失望。我很想用 Python 重写主应用程序 UI,让 C++ 做底层的所有事情,但它似乎并不实用,因为即使 wxGTK/C++ 在那个板上慢得令人无法接受。

多年来,我研究过许多不同的嵌入式 UI 工具包:Qt Embedded、GTK 和 GTK+、FLTK 等等。它们都不符合我在“Raspberry Pi 或更小一点”类别的板上运行嵌入式系统所需的功能、成熟度、国际化/本地化和速度标准。

现在,我觉得搜索可能已经结束,而解决方案一直就在我眼皮底下。由于对 Tcl/Tk 和 tkinter 的过时和不正确的态度,我从来没有关注它。

注意: 在现代 Python 中,旧的 Tkinter 模块已重命名为 tkinter,而 ttk 模块已成为它的子模块,因此当遗留代码执行 from Tkinter import * import ttk 时,现代(Python 3)代码将执行 from tkinter import * import tkinter.ttk 。此外,如果您在这些导入中遇到错误,指出无法加载模块 _tkinter ,则您的 Python 安装无法在其 LD_LIBRARY_PATH 或等效项上找到 _tkinter.so 或等效项,这可能是您的环境设置问题或你的 Python 构建。我不得不在 ARM 上从头开始构建 Python 2.7.10,然后进行一些摆弄以获取 _tkinter.so 进行构建。在构建过程中注意错误消息,并注意 tkinter 是作为“make install”而不是“make”的一部分构建的,至少在 Linux 上是这样。如果您的路径设置不正确,则构建可能无法找到 Tcl 和 Tk 标头以及共享库 按照 Stackoverflow 上此问题 的答案中所述设置 CPPFLAGS、LDFLAGS 和 LD_LIBRARY_PATH 可能会有所帮助。