作者 | 张江

发布 | ATYUN订阅号

有许多图形用户界面(GUI)工具包可以与Python编程语言一起使用。其中三巨头是Tkinter、wxPython和PyQt。这些工具包中的每一个都将与Windows、macOS和Linux一起工作,而PyQt具有在移动设备上工作的附加功能。

图形用户界面是一个具有按钮、窗口和许多其他小部件的应用程序,用户可以使用这些小部件与应用程序进行交互。web浏览器就是一个很好的例子。它有按钮、选项卡和一个主窗口,所有内容都在其中加载。

在本文中,你将学习如何使用wxPython GUI工具包用Python构建图形用户界面。

wxPython入门:GUI的定义

创建框架应用程序

创建工作应用程序

冲鸭!!!

wxpython入门

wxPython GUI工具包是一个围绕名为wxWidgets的c++库的Python包装器。wxPython的最初版本是在1998年发布的,所以wxPython已经存在很长时间了。wxPython与其他工具包(如PyQt或Tkinter)的主要区别在于,wxPython尽可能在本机平台上使用实际的小部件。这使得wxPython应用程序看起来与它所运行的操作系统是原生一体的。

PyQt和Tkinter都自己绘制小部件,这就是为什么它们并不总是去匹配本机小部件,尽管PyQt已经非常接近了。

这并不是说wxPython不支持自定义小部件。事实上,wxPython工具包包含了许多自定义小部件,以及几十个核心小部件。wxPython下载页面有一个名为Extra Files的部分,值得检查。

这里有一个wxPython演示包的下载。这是一个很好的小应用程序,演示了wxPython中包含的绝大多数小部件。演示允许开发人员在一个选项卡中查看代码,并在第二个选项卡中运行代码。你甚至可以在演示中编辑和重新运行代码,以查看更改如何影响应用程序。

安装wxPython

本文将使用最新的wxPython,即wxPython 4,也称为Phoenix发行版。wxpython3和wxpython2版本只针对python2构建。当wxPython的主要维护者Robin Dunn创建wxPython 4发行版时,他摒弃了许多别名,并清理了大量代码,以使wxPython更加python化,更易于维护。

现在可以使用pip安装wxPython 4,这在wxPython的旧版本中是不可能的。你可以按照以下步骤安装到你的电脑上:1$ pip install wxpython

注意:在Mac OS X上,你需要安装一个编译器,例如XCode,以便成功完成安装。Linux还可能要求你在pip安装程序正常工作之前安装一些依赖项。

例如,我需要在Xubuntu上安装freeglut3-dev、libgstreamer-plugins-base0.10-dev和libwebkitgtk-3.0-dev来安装它。

幸运的是,pip显示的错误消息有助于找出缺少内容,如果你想在Linux上安装wxPython,可以使用wxPython Github页面上的先决条件部分来帮助你找到所需的信息。

对于最流行的Linux版本,你可以在附带GTK2和GTK3版本的Extras Linux部分找到一些Python工具。要安装其中一个,可以使用以下命令:1$ pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04/ wxPython

确保你已经修改了上面的命令以匹配你的Linux版本。

GUI的定义

正如在介绍中提到的,图形用户界面(GUI)是在屏幕上绘制的供用户交互的界面。

用户界面有一些共同的组件:主窗口

菜单

工具栏

按钮

文本输入

标签

所有这些项目通常称为小部件。wxPython还支持许多其他常见的小部件和自定义小部件。开发人员将获取这些小部件,并将它们逻辑地排列在一个窗口上,以便用户与之交互。

事件循环

图形用户界面的工作原理是等待用户做一些事情。这个东西叫做事件。当用户在应用程序处于焦点时键入内容,或者当用户使用鼠标按下按钮或其他小部件时,就会发生事件。

在幕后,GUI工具包正在运行一个无限循环,称为事件循环。事件循环只是等待事件发生,然后根据开发人员编写应用程序要做的事情对这些事件进行操作。当应用程序没有捕获事件时,它实际上忽略了事件的发生。

当你在编写图形用户界面时,你需要记住,你需要将每个小部件连接到事件处理程序,以便你的应用程序能够执行一些操作。

在处理事件循环时,你需要记住一个特殊的注意事项:它们可能被阻塞。当你阻止一个事件循环时,GUI将变得无响应并对用户显示为冻结状态。

在GUI中启动的任何进程,如果耗时超过四分之一秒,都应该作为单独的线程或进程启动。这将防止GUI冻结,并为用户提供更好的用户体验。

wxPython框架有特殊的线程安全方法,你可以使用这些方法与应用程序通信,让它知道线程已经完成,或进行更新。

让我们创建一个框架应用程序来演示事件是如何工作的。

创建框架应用程序

GUI上下文中的应用程序框架是一个用户界面,其中包含没有任何事件处理程序的小部件。这些对于原型设计很有用。你只需创建GUI并将其呈现给涉众,以便在花大量时间处理后端逻辑之前进行签准。

让我们从使用wxPython创建Hello World应用程序开始:1import wx app = wx.App()frame = wx.Frame(parent=None, title='Hello World')frame.Show()app.MainLoop()

注意:Mac用户可能会得到以下信息:该程序需要访问屏幕。请使用python框架构建运行,并且只在登录到Mac主屏幕时运行。如果你看到这条消息,而不是在virtualenv中运行,那么你需要使用pythonw而不是python运行应用程序。

在本例中,你有两部分:wx.App和wx.Frame。的天气。App是wxPython的应用程序对象,是运行GUI所必需的。App启动一个名为. mainloop()的东西。这是你在前一节中了解到的事件循环。

另一块拼图是wx.frame,它将创建一个供用户交互的窗口。在本例中,你告诉wxPython框架没有父框架,它的标题是Hello World。下面是运行代码时的样子:

注意:当你在Mac或Windows上运行应用程序时,它看起来会有所不同。

默认情况下,wx.frame将包括沿顶部的最小化、最大化和退出按钮。不过,通常不会以这种方式创建应用程序。大多数wxPython代码将要求你子类化wx.frame和其他小部件,这样你就可以获得工具包的全部功能。

让我们花点时间重写你的代码作为一个类:

1import wx class MyFrame(wx.Frame):
2def __init__(self):
3super().__init__(parent=None, title='Hello World')
4self.Show() if __name__ == '__main__':
5app = wx.App()
6frame = MyFrame()
7app.MainLoop()

你可以将此代码用作应用程序的模板。但是,这个应用程序并没有做很多事情,所以让我们花点时间来了解一些你可以添加的其他小部件。

小部件

wxPython工具包有100多个小部件可供选择。这允许你创建丰富的应用程序,但是要想弄清楚要使用哪个小部件也可能会让人望而生畏。这就是为什么wxPython演示非常有用,因为它有一个搜索过滤器,你可以使用它来帮助你找到可能应用于项目的小部件。

大多数GUI应用程序允许用户输入一些文本并按下按钮。让我们继续添加这些小部件:

1import wx class MyFrame(wx.Frame):
2def __init__(self):
3super().__init__(parent=None, title='Hello World')
4panel = wx.Panel(self)
5self.text_ctrl = wx.TextCtrl(panel, pos=(5, 5))
6my_btn = wx.Button(panel, label='Press Me', pos=(5, 55))
7self.Show() if __name__ == '__main__':
8app = wx.App()
9frame = MyFrame()
10app.MainLoop()

当你运行这段代码时,你的应用程序应该如下所示:

需要添加的第一个小部件是wx.Panel。这个小部件不是必需的,但是推荐使用。在Windows上,你实际上需要使用一个面板,以便框架的背景颜色是正确的灰色阴影。如果在Windows上没有面板,则禁用选项卡遍历。

当你将panel小部件添加到框架中,并且该面板是框架的唯一子元素时,它将自动展开以填充框架。

下一步是添加一个wx.textcrl到面板。几乎所有小部件的第一个参数都是小部件应该指向哪个父部件。在本例中,你希望文本控件和按钮位于面板顶部,因此它是你指定的父控件。

你还需要告诉wxPython将小部件放置在何处,这可以通过pos参数传入一个位置来实现。在wxPython中,原点位置是(0,0),即父节点的左上角。因此,对于文本控件,你告诉wxPython要将其左上角距左侧(x) 5个像素和距顶部(y) 5个像素定位。

然后将按钮添加到面板并给它一个标签。为了防止小部件重叠,需要将按钮位置的y坐标设置为55。

好的,今天这一篇先更新到这里,我把这个过程分成三篇文章在接下来的两天里陆续更新,明天见~

End