wxPython和PyQt谁的Python GUI库最好?
外部
根据我们的经验,大部分用户在使用时一定是先关注应用的外观,所以我们先来对比一下wxPython和PyQt的外观。
WxPython是Python语言与流行的wxWidgets跨平台GUI工具库的绑定。WxWidgets是用C++语言编写的,所以当你在GUI中编写按钮小部件的代码时,你不会看到任何类似于另一个操作系统的东西。
▲基于Linux的Thunar和wxPython
PyQt也是用C++写的,基于著名的Qt工具包。与wxPython不同,它不使用native。
小部件,但是根据它检测到的操作系统创建一个小部件的近似。但是它的近似可以说是极端了,就连美术生也分不清它和原作的区别。
如果您使用KDE,您可以使用其他PyKDE库来弥补Linux和BSD之间原始PyQt和Plasma desktop外观之间的差距,但这增加了新的依赖性。
▲基于Linux的KDE和Qt
跨平台
WxPython和PyQt都支持Linux、Windows和Mac,所以非常适合跨平台。但是这种跨平台并不是无条件的。如果希望Python代码在特定平台上运行,需要做一些调整。例如,GUI工具包不能调整数据目录的路径格式,因此您必须运行Python中的最佳实践,使用os.path.join和几种不同的退出方法。GUI工具包的选择不会神奇地从平台中抽象出来。
PyQt试图消除跨平台差异,并允许Python本身需要的通用调整。PyQt可以避免大部分跨平台问题,所以GUI代码在不同的操作系统中基本可以保持不变。
在wxPython中,用户可能需要根据编程内容对不同平台的GUI代码进行一些调整。例如,为了防止Microsoft Windows上的某些元素闪烁,必须将USE_BUFFERED_DC属性设置为True,以便对图形进行双缓冲。这不是默认的,即使所有平台都可以无条件运行,所以在某些用例中可能会有缺陷。
固定
作为开发人员,您可能不关心获取应用程序所需的库所需的安装步骤;但是,如果您计划分发应用程序,您需要考虑用户为了使程序运行而必须执行的安装过程。
在所有平台上安装Qt就像安装任何其他应用程序一样简单。给用户一个下载链接,然后安装下载的软件包使用。
PyQt依赖于Qt本身的C ++代码,这意味着用户不仅要安装PyQt,还要安装所有的Qt。这个操作不像之前的安装那么简单,但是Qt和PyQt团队已经尽可能的简化了安装操作。现在只要用户可以安装浏览器或者游戏,就可以通过链接成功安装Qt。如果用户非常擅长,用户甚至可以将安装脚本作为自己安装程序的一部分。
在Linux、BSD和Ilumos中,安装程序通常由经销商的软件包管理员为用户编写。
在Linux和Windows上,wxPython的安装过程非常简单,但是在Mac OS上就有问题了。如果可下载的软件包严重过时,Mac OS不利于向后兼容。由于该修补程序的错误代码,该软件包尚未更新,因此用户自己找到并实施该修补程序的机会非常低。目前的解决方案是将wxPython打包分发给Mac OS用户,或者依靠外部的包管理器。
组件和功能
PyQt和wxPython都有用户期望从GUI工具包中得到的所有公共小部件(包括按钮、复选框、下拉菜单等)。).两者都支持拖放操作、选项卡式界面、对话框和创建自定义小部件。
PyQt的优势在于灵活性。您可以在运行时重新排列、浮动、关闭和恢复Qt面板,为每个应用程序提供一个高度可配置的以可用性为中心的界面。
只要使用正确的小部件,就可以为用户提供许多友好的功能,而不必自己重新思考花哨的技能。
WxPython有很多好的功能,但是在灵活性和用户控制上是无法和PyQt相比的。PyQt更便于开发者设计和布局。在开发Qt之前,需要花一些时间从用户那里获取跟踪自定义布局的方法,或者如何找到不小心关闭的缺失面板。对于wxPython,很难重新打开意外关闭的面板。
一般来说,wxPython只是wxWidgets的前端,所以如果真的需要一个函数,可以用C ++实现,然后在wxPython中使用。与PyQt相比,wxPython的学习曲线更加陡峭。
沟通
GUI应用程序由许多较小的可视元素组成,通常称为“小部件”。为了让GUI应用程序顺利运行,小部件必须相互通信。例如,用于显示图像的窗格可以知道用户选择了哪个缩略图。包括wxPython在内的大多数GUI工具包都可以用“回调”来处理内部通信。回调是指向一段代码(“函数”)的指针。如果当你点击一个按钮部件时发生了什么,你应该为发生的操作写一个函数。当点击按钮时,功能被触发,操作发生。
如果和Lambda表达式结合,会产生非常灵活的解决方案,效果可能会超出你的预期。
另一方面,Qt以其信号/插槽机制而闻名。如果把wxPython的内部通信网络比作一个老式的电话交换机,那么PyQt的通信可以看作是一个网状网络。
▲Qt中的信号和插槽
Qt使用信号和插槽,而不是回调函数。当特定事件发生时,信号会被发出。Qt的小部件有许多预定义的信号。当然,我们也可以创建widget的子类来添加我们需要的自定义信号。Slot是对特定信号的反馈。Qt的widget也有许多预定义的插槽,但通常的做法是创建widget的子类,并添加自定义插槽来处理感兴趣的信号。
信号和插槽机制是类型安全的:信号的参数必须与接收插槽的参数相匹配。由于这种参数匹配机制,编译器可以帮助我们检查类型不匹配的签名。信号和插槽是松散耦合的:信号类既不知道也不关心哪个插槽接收信号。Qt的信号和插槽机制确保了如果你将一个信号连接到一个插槽,这个插槽将在正确的时间被number参数调用。信号和槽可以携带任意数量的任意类型的参数。它们是完全类型安全的。
从QObject或它的一个子类(比如QWidget)继承的所有类都可以使用数字和槽。对象之间的通信是这样的,一个对象的状态发生变化,发出一个信号,另一个关心这个变化的对象收到这个信号。发送信号的对象不知道或者对什么对象接收它发送的信号不感兴趣。这是真正的信息封装,确保对象可以作为软件组件使用。
插槽可以用来接收信号,但也是普通的成员函数。插槽不知道是否有信号连接到它,就像对象不知道它发出的信号是否会被接收到一样。这种机制确保Qt可以用来创建完全独立的组件。
信号可以多对多的方式连接到插槽。这样,信号和插槽就建立了一个强大的组件编程机制。
总体布局
要编写一个GUI应用程序,要做的第一件事就是设计布局,以便所有的小部件都可以正确地显示在应用程序窗口中。就像设计网页一样,您可以调整应用程序的大小,甚至可以将其设置为固定大小。
在Qt中,布局非常流畅,Widget命名清晰(QPushButton、QDial、QCheckbox、QLabel,甚至QCalendarWidget),而且调用方便,连应用文档都很齐全。
这里的大部分困惑集中在基本的GUI元素上。比如你在写一个应用,可以从QMainWindow或者QWidget构建你的父窗口吗?
QWidget是一个空容器,所有其他小部件都可以使用它。当然,可以放置更多的QWidgets,形成一个放置更多Widgets的父窗口。QMainWindow使用的是QWidget,增加了很多大多数应用都需要的便捷功能,比如顶部的工具栏,底部的状态栏。
▲QMainWindow
这是一个使用QMainWindow的小型文本编辑器,只有100行Python代码:
wxPython中的基本小部件是wx。wxPython中的一切都是基于wx的。窗口类,不管它是实际的窗口还是按钮、复选框或文本标签。如果类名拼写错误,wx。Window会直接忽略它。
下图是用wx创建一个空窗口。框架:
将其他部件放入wx。框架窗口,然后构建一个GUI应用程序。比如wx。Panel小部件类似于HTML中的div,具有绝对大小限制,因此您可以使用它在主窗口中创建面板。
与PyQt相比,WxPython的便捷功能较少。比如PyQt内置了复制粘贴功能,但是在wxPython中必须手动编码(而且有些还受限于运行的平台)。