用wxPython打造Python图形界面

本文目录:

  • 绝对定位
  • 分级器(动态分级)
  • 添加一个事件
  • 创建工作应用程序
  • 设计用户界面
  • 创建用户界面

绝对定位

当你为小部件的位置提供精确的坐标时,使用的技术称为绝对定位。大多数GUI工具包都提供了这种功能,但实际上并不推荐使用这种功能。

随着应用程序变得越来越复杂,要跟踪所有小部件的位置以及是否必须移动小部件就变得非常困难。重置所有这些位置将成为一场噩梦。

幸运的是,所有现代GUI工具包都为此提供了一个解决方案,这是你接下来要学习的内容。

分级器(动态分级)

wxPython工具包包括用于创建动态布局的sizer。它们为你管理小部件的位置,并在你调整应用程序窗口大小时对其进行调整。其他GUI工具包将sizer称为布局,PyQt就是这样做的。

以下是你将看到最常用的几种主要sizer类型:

  • BoxSizer
  • GridSizer
  • FlexGridSizer

加上wx.BoxSizer的例子,看看我们是否可以让它更好地工作:

 1 import wx
 2 class MyFrame(wx.Frame):    
 3    def __init__(self):
 4        super().__init__(parent=None, title='Hello World')
 5        panel = wx.Panel(self)        
 6        my_sizer = wx.BoxSizer(wx.VERTICAL)        
 7        self.text_ctrl = wx.TextCtrl(panel)
 8        my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5)        
 9        my_btn = wx.Button(panel, label='Press Me')
10        my_sizer.Add(my_btn, 0, wx.ALL | wx.CENTER, 5)        
11        panel.SetSizer(my_sizer)        
12        self.Show()
13
14 if __name__ == '__main__':
15    app = wx.App()
16    frame = MyFrame()
17    app.MainLoop()

这里创建一个wx.boxsizer实例。拳击手,并将其传递给wx.vertical,这是将小部件添加到sizer的方向。

在本例中,小部件将垂直添加,这意味着它们将依次从上到下逐个添加。你还可以将BoxSizer的方向设置为wx.HORIZONTAL。当你这样做时,小部件将从左到右添加。

要将小部件添加到sizer,你将使用. add()。它最多接受5个参数

  • 窗口(小部件)
  • 比例
  • 旗帜
  • 边境
  • 用户数据

window参数是要添加的小部件,而proportion设置相对于sizer中其他小部件的空间大小。默认情况下,它是零,它告诉wxpython将小部件保留在其默认比例。

第三个参数是flag。如果你希望传递多个标志,只要用管道字符分隔它们:。wxpython工具包使用添加使用一系列按位ORS的标志。

在本例中,将添加带有wx.all和wx.expand标志的文本控件。wx.all标志告诉wxpython要在小部件的所有边上添加边框,而wx.expand使小部件在sizer中尽可能地展开。

最后,你还有border参数,它告诉wxpython你想要在小部件周围有多少像素的border。只有当你想对小部件进行复杂的调整时,才使用userdata参数,实际上在实践中很少看到它。

向sizer添加按钮的步骤完全相同。但是,为了让事情变得更有趣,我打开了wx.center的wx.expand标志,以便按钮在屏幕上居中。

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

添加一个事件

虽然你的应用程序在视觉上看起来更有趣,但它仍然没什么用。例如,如果你按下按钮,什么都不会发生。

所以让我们给按钮一个任务:

 1 import wx
 2
 3 class MyFrame(wx.Frame):    
 4    def __init__(self):
 5        super().__init__(parent=None, title='Hello World')
 6        panel = wx.Panel(self)        
 7        my_sizer = wx.BoxSizer(wx.VERTICAL)        
 8        self.text_ctrl = wx.TextCtrl(panel)
 9        my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5)        
10        my_btn = wx.Button(panel, label='Press Me')
11        my_btn.Bind(wx.EVT_BUTTON, self.on_press)
12        my_sizer.Add(my_btn, 0, wx.ALL | wx.CENTER, 5)        
13        panel.SetSizer(my_sizer)        
14        self.Show()
15
16    def on_press(self, event):
17        value = self.text_ctrl.GetValue()
18        if not value:
19            print("You didn't enter anything!")
20        else:
21            print(f'You typed: "{value}"')
22
23 if __name__ == '__main__':
24    app = wx.App()
25    frame = MyFrame()
26    app.MainLoop()

wxPython中的小部件允许你将事件绑定附加到它们,以便它们能够响应特定类型的事件。

注意:上面的代码块使用f-string。

当用户按下按钮时,你希望该按钮执行某些操作。你可以通过调用按钮的. bind()方法来实现这一点,. bind()获取你希望绑定到的事件、事件发生时要调用的处理程序、一个可选源和几个可选id。

在本例中,将button对象绑定到wx.evt_button事件,并告诉它在触发该事件时调用on_press()。

当用户执行所绑定的事件时,事件将被“触发”。在本例中,你设置的事件是按钮按下事件wx.EVT_BUTTON。

.on_press()接受第二个可以调用event的参数。这是惯例。如果你愿意,你可以叫它别的名字。然而,这里的event参数指的是这样一个事实:当调用这个方法时,它的第二个参数应该是某种类型的event对象。

在.on_press()中,你可以通过调用文本控件的GetValue()方法来获取文本控件的内容。然后根据文本控件的内容将字符串打印到stdout。

现在你已经掌握了基本知识,让我们学习如何创建一个做一些有用的事情的应用程序!

创建工作应用程序

创建新东西的第一步是弄清楚你想要创建什么。在这种情况下,我冒昧地为你做了这个决定。你将学习如何创建一个MP3标签编辑器!创建新东西的下一步是找出哪些包可以帮助你完成任务。

如果你做一个谷歌搜索Python mp3标签,你会发现你有几个选项:

  • mp3-tagger
  • eyeD3
  • mutagen

我试用了其中的一些,认为eyeD3有一个很好的API,你可以使用它而不会被MP3的ID3规范所困扰。你可以使用pip安装eyeD3,如下所示:

1$ pip install eyed3

在macOS上安装这个包时,可能需要使用brew安装libmagic。Windows和Linux用户安装eyeD3应该没有任何问题。

设计用户界面

当涉及到设计一个界面的时候,最好能大致勾勒出你认为用户界面应该是什么样的。

你需要具备以下能力:

  • 打开一个或多个MP3文件
  • 显示当前MP3标签
  • 编辑MP3标签

大多数用户界面使用菜单或按钮来打开文件或文件夹。你可以使用文件菜单执行此操作。由于你可能希望看到多个MP3文件的标记,因此需要找到一个小部件,它可以以一种良好的方式完成这一任务。

用列和行组成的表格是理想的,因为这样你就可以为MP3标记列。wxPython工具包有几个小部件可以实现这一点,前两个小部件如下:

  • grid.Grid
  • ListCtrl

在这种情况下,你应该使用wx.listcrl,因为网格小部件过于复杂,坦率地说,它也相当复杂。最后,你需要一个按钮来编辑选定的MP3标签。

现在你知道你想要什么了,你可以把它画出来:

上面的插图让我们了解了应用程序的外观。现在你知道你想做什么了,是时候编码了!

创建用户界面

在编写新应用程序时,有许多不同的方法。例如,你是否需要遵循模型-视图-控制器设计模式?你是怎么划分等级的?每个文件一个类?有很多这样的问题,随着你对GUI设计有了更多的经验,你将知道如何回答它们。

在你的例子中,你只需要两个类:

  • A wx.Panel class
  • A wx.Frame class

你也可以创建控制器类型模块,但是对于这样的事情,你实际上并不需要它。也可以将每个类放到它自己的模块中,但是为了保持紧凑,你需要为所有代码创建一个Python文件。

让我们从导入和面板类开始:

 1 import eyed3
 2 import glob
 3 import wx
 4
 5 class Mp3Panel(wx.Panel):
 6    def __init__(self, parent):
 7        super().__init__(parent)
 8        main_sizer = wx.BoxSizer(wx.VERTICAL)
 9        self.row_obj_dict = {}
10        self.list_ctrl = wx.ListCtrl(
11            self, size=(-1, 100),
12            style=wx.LC_REPORT | wx.BORDER_SUNKEN
13        )
14
15        self.list_ctrl.InsertColumn(0, 'Artist', width=140)
16        self.list_ctrl.InsertColumn(1, 'Album', width=140)
17        self.list_ctrl.InsertColumn(2, 'Title', width=200)
18        main_sizer.Add(self.list_ctrl, 0, wx.ALL | wx.EXPAND, 5)       
19        edit_button = wx.Button(self, label='Edit')
20        edit_button.Bind(wx.EVT_BUTTON, self.on_edit)
21        main_sizer.Add(edit_button, 0, wx.ALL | wx.CENTER, 5)       
22        self.SetSizer(main_sizer)
23
24    def on_edit(self, event):
25        print('in on_edit')
26
27    def update_mp3_listing(self, folder_path):
28        print(folder_path)
29

在这里,你为你的用户界面导入了eyed3包、Python的glob包和wx包。接下来,将子类wx.pane子类化并创建用户界面。你需要一个字典来存储有关mp3的数据,可以将其命名为row_obj_dict。

然后创建一个wx.listcrl并将其设置为具有凹陷边框(wx.border_u sunken)的报告模式(wx.lc_ report)。根据传入的样式标志,列表控件可以采用其他几种形式,但报表标志最受欢迎。

要使ListCtrl具有正确的标题,需要为每个列标题调用. insertcolumn()。然后提供列的索引、标签以及列的宽度(以像素为单位)。

最后一步是添加编辑按钮、事件处理程序和方法。你可以创建到事件的绑定,并将其调用的方法暂时保留为空。

现在你应该为框架编写代码:

 1 class Mp3Frame(wx.Frame):
 2    def __init__(self):
 3        super().__init__(parent=None,title='Mp3 Tag Editor')
 4        self.panel = Mp3Panel(self)
 5        self.Show()
 6
 7 if __name__ == '__main__':
 8    app = wx.App(False)
 9    frame = Mp3Frame()
10    app.MainLoop()

这个类比第一个类简单得多,你只需设置框架的标题并实例化panel类Mp3Panel。当你完成所有操作后,你的用户界面应该如下所示:

用户界面看起来几乎正确,但是没有文件菜单。这使得向应用程序添加mp3并编辑它们的标记是不可能的!

End

原文发布于微信公众号 - ATYUN订阅号(atyun_com)

原文发表时间:2019-04-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券