wxpython可视化_极易上手的可视化wxPython GUI构建工具(wxFormBuilder)-嵌入式系统-与非网...

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是 wxPython GUI 构建工具 wxFormBuilder。

一、手工代码布局 GUI 界面的烦恼

如果你曾经设计过上位机软件GUI 界面,初始阶段一定是纯手工代码布局 GUI界面上的各个控件,相信你肯定遇到过如下烦恼:

控件类型较难找:UI 界面里有很多控件类型,纯手工写代码需要翻看文档一个个去查找这些控件的名字与用法。

尺寸位置难调整:如果界面上已经布了多个控件,想要整体去调整这些控件的尺寸与位置是一件头疼的事。

效果查看不实时:每新添加一个控件都需要运行才能查看整体效果,如果代码添加不完善,可能无法运行看不到效果。

二、wxFormBuilder 工具背景

在讲本文主角 wxFormBuilder 之前有必要提一下这个软件的来历,首先要追述到大名鼎鼎的跨平台 GUI 库 wxWidgets,这个库主要是用 C++语言实现的;鉴于 wxWidgets 的流行,Robin Dunn 用 Python 语言对 wxWidgets 做了一层封装,封装后便成了 Python 版 GUI 库 wxPython;下面是这两个 GUI 库的官方主页:

wxWidgets 项目官方主页: https://www.wxwidgets.org/

wxPython 项目官方主页: https://www.wxpython.org/

wxWidgets 的各种 UI 控件功能均是通过 class 来实现的,这个链接 http://docs.wxwidgets.org/3.0/page_class_cat.html 列出了 wxWidgets 里的所有 class,wxPython 并没有实现 wxWidgets 里全部 class,但基本实现了大部分常用 class,这个链接 https://docs.wxpython.org/wx.1moduleindex.html 列出了 wxPython 里所有的 class。

知道了 wxPython 的 class 便可以开始设计 GUI 界面,但手工写代码设计界面太繁琐,因此 wxFormBuilder 应运而生,这是一款能够可视化设计界面的工具(并不是唯一工具,还有 wxGlade、Boa Constructor 等),通过该工具设计 GUI 界面后可自动生成 wxPython 代码,下面是 wxFormBuilder 的官方主页:

wxFormBuilder 项目 Github: https://github.com/wxFormBuilder/wxFormBuilder

三、wxFormBuilder 快速上手

使用 wxFormBuilder 去设计 GUI 界面可以不用掌握 wxPython 里的各个控件 class 的具体用法,你只需要在 wxFormBuilder 软件里添加这些控件即可,下面痞子衡将简介 wxFormBuilder 的用法:

3.1 软件界面

安装好 wxFormBuilder 软件之后打开这个软件,可见到如下界面,界面主要分为四大区:项目区、控件区、编辑区、属性区。软件使用起来非常简单,就是在【控件区】里点击添加需要的控件,这些控件的效果会在【编辑区】里实时显示,并在【属性区】这些控件的属性,【项目区】用于显示控件间的层级关系。

5e34cab66163c-thumb.png

3.2 基础布局

让我们开始创建一个 GUI 的基础框架,基础框架包括:Frame(外围轮廓)、Sizer(内部控件区)、menubar(顶部菜单栏)、statusBar(底部状态栏)。

第一步是添加一个 Frame,这是 GUI 的轮廓基础,其 size(default 为 500;300)决定了 GUI 整体界面的大小。

5e34cab674a59-thumb.png

第二步是在 Frame 下添加一个 Sizer,后续所有控件均是放在 Sizer 里的。关于 Sizer 部分需要特别说明一下,wxPython 提供的 Sizer 类型有如下七种:wxBoxSizer、wxWrapSizer、wxStaticBoxSizer、wxGridSizer、wxFlexGridSizer、wxGridBagSizer、wxStdDialogButtonSizer,Sizer 的样式决定了后续控件的整体相对位置关系,选定了 Sizer 即选定了 GUI 界面样式。关于这七种 Sizer 的具体样式请见 https://docs.wxpython.org/sizers_overview.html#sizers-overview。如果你觉得单个 Sizer 里的控件布局太单调,你可以嵌套使用 Sizer,这是实现 GUI 界面控件布局多样化的关键。

5e34cab67add5-thumb.png

第三步是在 Frame 顶部添加一个 menubar:

5e34cab710db3-thumb.png

第四步是在 Frame 底部添加一个 statusBar:

5e34cab6b5952-thumb.png

3.3 多种控件

基础布局搞定之后,接下来便是在 Sizer 里添加控件,wxPython 支持的控件非常丰富,其中比较常用的是如下几个:button(按钮)、staticText(静态显示文本框)、textCtrl(输入输出文本框)、Choice(复选框)、checkBox(选中框)、slider(滑动条)。前面痞子衡选择的 Sizer 是 wxBoxSizer,即自上而下布局,因此这些控件在 Sizer 是自上而下排列的,各个控件的位置后续在属性里还可以微调,但改变不了自上而下的格局。

5e34cab6b5174-thumb.png

3.4 控件属性

添加了所有控件之后,下一步便是分别设置控件的属性,进一步调整控件。痞子衡以 Button 属性为例,痞子衡勾选了如下 4 项比较重要的属性设置,分别是 name(button 在后续 python 代码的对象名,一般需要按其功能修改,修改后使得代码阅读 / 修改起来更直观)、label(button 在 GUI 里显示的标签名,此处是 MyButton,也需要按其功能修改,方便用户使用软件)、size(设置 button 的尺寸,这个尺寸最大不应超过 Sizer 尺寸)、flag(调整对齐方式从而调整 Button 在 Sizer 里的位置)。另外有一个属性不得不说,即控件位置 pos,在 wxFormBuilder 里设置这个属性并不生效,痞子衡猜想可能跟 Sizer 样式有关,因为 Sizer 决定了控件间相对位置关系,因此控件的 pos 不能随意设置。

5e34cab7870c0-thumb.png

3.5 触发事件

有些控件是需要有响应的,比如 Button,在 GUI 软件实际使用中,用户如果按下了 Button,应该需要触发某个任务,任务需要有响应函数,这个响应函数需要在【Events】里设置,Button 的响应函数在 OnButtonClick 里设置,痞子衡在这里指定了响应函数名为 showMessage。在 wxFormBuilder 里我们只需要指定控件响应函数名即可,响应函数的具体功能实现,不属于 wxFormBuilder 设计范畴。

5e34cab75ea6c-thumb.png

3.6 生成代码

当 GUI 界面布局全部完成之后,需选择 File->Generate Code 或 F8 生成 python 代码,需要复制所有的 python 代码并保存在单独的文件里,痞子衡保存在了 my_win.py 文件里。

5e34cab78301b-thumb.jpg

可以简单看一下这个 my_win.py 里的内容,代码里首先 import 了 wx 库(即 wxPython 库),并定义了名为 MyFrame1 的 class,这个 class 主要包含两个函数 __init__()和 showMessage():__init__()里初始化了各个控件成员 self.m_xx,这与我们在 wxFormBuilder 里添加控件是对应的;showMessage()是 Button 控件的响应函数,但这个响应函数并没有任何实质代码,当然我们可以在这个函数里面实现 Button 响应功能,但一般不建议直接在 wxFormBuilder 生成的代码里添加代码,因为你可能随时调整 GUI 页面布局,那么 main_win.py 里的代码会重新生成,这样会覆盖我们自己添加的代码,导致维护起来比较麻烦。

# -*- coding: utf-8 -*-

###########################################################################

## Python code generated with wxFormBuilder (version Jul 11 2018)

## http://www.wxformbuilder.org/

##

## PLEASE DO *NOT* EDIT THIS FILE!

###########################################################################

import wx

import wx.xrc

###########################################################################

## Class MyFrame1

###########################################################################

class MyFrame1 ( wx.Frame ):

def __init__( self, parent ):

wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )

bSizer1 = wx.BoxSizer( wx.VERTICAL )

self.m_button1 = wx.Button( self, wx.ID_ANY, u"MyButton", wx.Point( -1,-1 ), wx.DefaultSize, 0 )

bSizer1.Add( self.m_button1, 0, wx.ALL, 5 )

self.m_staticText1 = wx.StaticText( self, wx.ID_ANY, u"MyLabel", wx.DefaultPosition, wx.DefaultSize, 0 )

self.m_staticText1.Wrap( -1 )

bSizer1.Add( self.m_staticText1, 0, wx.ALL, 5 )

self.m_textCtrl1 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.Point( -1,-1 ), wx.DefaultSize, 0 )

bSizer1.Add( self.m_textCtrl1, 0, wx.ALL, 5 )

m_choice1Choices = []

self.m_choice1 = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice1Choices, 0 )

self.m_choice1.SetSelection( 0 )

bSizer1.Add( self.m_choice1, 0, wx.ALL, 5 )

self.m_checkBox1 = wx.CheckBox( self, wx.ID_ANY, u"Check Me!", wx.DefaultPosition, wx.DefaultSize, 0 )

bSizer1.Add( self.m_checkBox1, 0, wx.ALL, 5 )

self.m_slider1 = wx.Slider( self, wx.ID_ANY, 50, 0, 100, wx.DefaultPosition, wx.DefaultSize, wx.SL_HORIZONTAL )

bSizer1.Add( self.m_slider1, 0, wx.ALL, 5 )

self.SetSizer( bSizer1 )

self.Layout()

self.m_menubar1 = wx.MenuBar( 0 )

self.m_menu1 = wx.Menu()

self.m_menuItem1 = wx.MenuItem( self.m_menu1, wx.ID_ANY, u"MyMenuItem", wx.EmptyString, wx.ITEM_NORMAL )

self.m_menu1.Append( self.m_menuItem1 )

self.m_menubar1.Append( self.m_menu1, u"MyMenu" )

self.SetMenuBar( self.m_menubar1 )

self.m_statusBar1 = self.CreateStatusBar( 1, wx.STB_SIZEGRIP, wx.ID_ANY )

self.Centre( wx.BOTH )

# Connect Events

self.m_button1.Bind( wx.EVT_BUTTON, self.showMessage )

def __del__( self ):

pass

# Virtual event handlers, overide them in your derived class

def showMessage( self, event ):

event.Skip()

四、使用 wxFormBuilder 生成的代码

前面已经使用 wxFormBuilder 生成 GUI 界面类 MyFrame1 并保存在 my_win.py 文件中,此时需要创建一个主函数文件去调用 MyFrame1,下面是痞子衡创建的 main_win.py 中的代码:

import wx

# 导入 my_win.py 中内容

import my_win

# 创建 mainWin 类并传入 my_win.MyFrame1

class mainWin(my_win.MyFrame1):

# 实现 Button 控件的响应函数 showMessage

def showMessage(self, event):

self.m_textCtrl1.Clear()

self.m_textCtrl1.SetValue('hello world')

if __name__ == '__main__':

# 下面是使用 wxPython 的固定用法

app = wx.App()

main_win = mainWin(None)

main_win.Show()

app.MainLoop()

最后让我们测试一下这个 GUI 软件,在命令行下运行 main_win.py

PS D:\my_git_repo\> python .\main_win.py

5e34cab73fb27-thumb.png

至此,wxPython GUI 构建工具 wxFormBuilder 痞子衡便介绍完毕了,掌声在哪里~~~

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个VB6的IDE插件(Addin),使用VB6的IDE直接设计Python的界面。 Python和VB都是能让人快乐的编程语言,我使用了Python之后,很多自己使用的工具都使用Python开发或改写了,因为最终实现的Python代码实在太短了(相比VB),有时候Python一行代码就可以实现VB一个函数的功能。 Python就是这种让人越用越开心的语言。 不过说实在,使用Python开发GUI界面还是麻烦了一些了,自带的标准库Tkinter使用起来非常简单,不过对于习惯了VB拖放控件完成界面设计的同学来说,还是不够人性化。TK也有一个工具GUI Builder,不过它使用Layout布局,不够直观,而且界面简陋,用起来也不爽。 至于PyQt/wxPythonGUI库,尽管有可视化设计工具,但总感觉做一般的轻量级应用是杀鸡用牛刀,学习起来也比较复杂,而且不够环保,不够低碳,要带一个很大的库,需要目标机器上夜同样安装了PyQt/wxPython,做不了绿色软件。 所以最终的结果是我更喜欢Tkinter,用起来很简单,绿色环保,真正的跨平台,一个py文件到处运行(担心泄密就编译成pyc)。 很多人都认为TK的界面不够美观,不过导入Python自带的标准TTK主题库,界面非常Native,不输PyQt/wxPython。 此Addin默认启用TTK支持,也可选择关闭。 总而言之,轻量级GUI,TK+TTK足够。 使用此Addin,你可以不用写一句代码就可以生成一个完整可运行的Python的GUI界面,支持python 2.X和3.X。 安装方法:将压缩包解压到你希望的目录,然后执行Setup.exe完成注册插件过程,打开VB6就可以用了。 在VB窗体上设计完成界面后(你可以大胆的设置各控件的属性,Addin尽量将其翻译为tkinter的控件属性),点工具栏上的VisualTkinter(图标为一片橙红色羽毛),再点'生成代码'按钮,即可生成可运行的Python代码,可以拷贝至剪贴板或保存至文件。 一般情况下你可以不用再改变tkinter的控件属性,但是如果你熟悉tkinter,需要更多的控制,可以一一核对各属性,并且修改,再生成代码。 除了用来设计界面外,此ADDIN内置的各控件属性列表可以做为编程参考,比较完整,除了极少数我认为大多数人都不用的属性外,属性定义基本上是我从官方的tkinter文档直接翻译的。 如果还没有VB6,上找一个VB6精简版即可(建议使用12M的版本,6M的版本也可以使用,不过工具栏图标无法显示,可以通过菜单执行此插件)。 经过友测试,完美支持WinXP,Windows 7, Windows 8。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值