wxFormBuilder + wxPython手撸丑陋计算器
目录
前言
一、设计计算器图形界面
1、建Project
2、设计主体框的属性
3、设计计算器页面布局
二、代码架构设计
1、将计算器运行起来
2、添加按钮事件
3、代码实现
4、运行计算器
三、测试计算器逻辑
前言
wxPtyhon它是Python语言的跨平台GUI工具包。使用wxPython软件开发人员可以为他们的Python应用程序创建真正的本地用户界面。
wxFormBuilder是一个图片界面生成器,其生成的界面可以翻译成为C++、python、PHP、Lua、XRC代码。本文开源,跨平台,自动生成生成代码,提高开发效率的特性,用不用它,仁者见仁,智者见智。用熟悉了,什么工具都可达到最终目的,也可以不用工具,直接使用GUI库手撸客户端工具,大神一般是这么做的。所以本文适合刚上手wxPython,但又急于想开发客户端工具的人看。
本文会仔细描述wxFormBuilder如何拖拽出一个丑陋的计算器,生成wxPython代码;然后在这个基础上再描述实现计算器的计算功能的过程
代码编器使用PyCharm,阅读本文需要有Python基础,略微了解wxPython。
丑陋的计算器呈现效果如下(后期可能更丑~~~~)
一、设计计算器图形界面
1、建Project
打开wxFormBuilder,
在Object Tree树下选择MyProject1:Project、
点击Component Palotte 下Forms 的Tab页,点击Frame按钮(第一个),
按下图数字标识,生成一个Frame框。这将会是计算器的主体。
2、设计主体框的属性
属性Object Properties------ProperTies
去掉标题栏
Frame-----style 下的wxDEFAULT_FRAME_STYLE 取消勾选,
标题栏去掉,最大化、最小化、关闭按钮跟着一并去掉了
设置size
最小为宽400px;长500px
wxWindow-----minimum_size设置400;500,
size 宽为400px:可横向摆上4例按钮 ,
size 高为500px:可竖向摆上1个显示屏与5行按钮
3、设计计算器页面布局
先将计算器画一下,明确布局,使用WxBoxSize布局
上图标1是显示屏,占WxBoxSize一栏
上图标2是按钮区,占WxBoxSize一栏
上图标3是按钮分区,在2栏里嵌套一个WxBoxSize
1)添加布局、显示
在Object Tree选择MyFrame1:Frame,然后在Component Palatte里选择Layout布局Tab页,选择WxBoxSize添加
按图中数字顺序操作
在bSizer1:wxBoxSize第一栏添加一个Text,
Common 页中选择编辑框
按图中数字顺序操作
在BSizer1中添加一个wxBoxsize
选择BSizer1:wxBoxSizer,进入Layout 页,添加一个WxBoxSizer,将这个WxBoxSizer的orient设置为WxHORIZONTAL (横向)
按图中数字顺序操作
在bSizer2中添加四个WxBoxSizer,
操作方法与上面一样,只是添加一个,orient默认不动,此时主体框还看不出什么
按图中数字顺序操作
添加按钮,在BSizer3、BSizer4、BSizer5、BSizer6下,各添加5个按钮,
调整所有按钮最小Size为70px; 60px
按图中数字顺序操作
设置显示屏属性与按钮字符修改
显示屏样式
Size设置:Minimum_size:370;80
只读:wxREADONLY
靠右:wxTE_RIGHT
多行:wxTE_MULTILINE
自行展示滚动条:wxTE_RICH --------行数超过显示屏展示滚动条,未超过不展示
显示屏中字体大小样式,因为这个wxFormBuilder可能没装好,无法设置,后期在代码里修改
修改按钮展示字符,点击目标按钮,在Properties里找到label,改变其值,如下图
按图中数字顺序操作
注意:修改属性时,切换控件请勿直接点击另一个控件,大概率会导致wxFormBuilder崩溃。可以先点击上图3处空白地段,再点击另一个控件,这样就不会使wxFormBuilder崩溃。
修改完按钮字符后,
将第四列按钮删除一个,=号按钮高度调整为125px
再将主体框高度调整为450px
这里只给描述没给操作步骤,请自行按照前面的操作修改对应参数。
计算器框效果图如下
wxFormBuilder部分完成,接下来将将Editer由Designer切换到下图Python页,复制其中的py代码到下个章节开始做计算器后台逻辑的开发
生成的代码重新给了相关注释,输出如下:
# -*- coding: utf-8 -*-###########################################################################
## Python code generated with wxFormBuilderormBuilder (version Jun 17 2015)
## http://www.wxFormBuilderormbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE!
###########################################################################
#导入wxPython相关的库
import wx
import wx.xrc###########################################################################
## Class MyFrame1
###########################################################################class MyFrame1 ( wx.Frame ):
#初始化构造框体,
def __init__( self, parent ):#初始化父类,构造Frame框体,传入了父类对象,框体id,框体title,位置pos,大小size,风格style
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( -1,-1 ), style = 0|wx.TAB_TRAVERSAL )#设置框体大小,这里正式使用时要将self.SetSizeHintsSz改为self.SetSizeHints,国为self.SetSizeHintsSz是比较老版本wxPython中的方法了,新方法去掉了末尾Sz
self.SetSizeHintsSz( wx.Size( 400,450 ), wx.DefaultSize )#创建第一个布局BoxSizer 为 bSizer1,纵向的
bSizer1 = wx.BoxSizer( wx.VERTICAL )#创建编辑框
self.m_textCtrl1 = wx.TextCtrl( self, wx.ID_ANY, u"1+2=\n3", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH|wx.TE_RIGHT )#设置编辑框的大小
self.m_textCtrl1.SetMinSize( wx.Size( 370,80 ) )#将编辑框加入到 bSizer1中去
bSizer1.Add( self.m_textCtrl1, 0, wx.ALL, 5 )#创建第二个布局BoxSizer 为 bSizer2,横向的
bSizer2 = wx.BoxSizer( wx.HORIZONTAL )#创建第三个布局BoxSizer 为 bSizer3,纵向的
bSizer3 = wx.BoxSizer( wx.VERTICAL )#创建第一个button按钮为m_button1
self.m_button1 = wx.Button( self, wx.ID_ANY, u"C", wx.DefaultPosition, wx.DefaultSize, 0 )#设置按钮的大小
self.m_button1.SetMinSize( wx.Size( 70,60 ) )#将m_button1加入后bSizer3中
bSizer3.Add( self.m_button1, 0, wx.ALL, 5 )self.m_button2 = wx.Button( self, wx.ID_ANY, u"7", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button2.SetMinSize( wx.Size( 70,60 ) )bSizer3.Add( self.m_button2, 0, wx.ALL, 5 )self.m_button3 = wx.Button( self, wx.ID_ANY, u"4", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button3.SetMinSize( wx.Size( 70,60 ) )bSizer3.Add( self.m_button3, 0, wx.ALL, 5 )self.m_button4 = wx.Button( self, wx.ID_ANY, u"1", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button4.SetMinSize( wx.Size( 70,60 ) )bSizer3.Add( self.m_button4, 0, wx.ALL, 5 )self.m_button17 = wx.Button( self, wx.ID_ANY, u"%", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button17.SetMinSize( wx.Size( 70,60 ) )bSizer3.Add( self.m_button17, 0, wx.ALL, 5 )#将纵向的bSizer3加入到横向的bSizer2中,实现例。后面还有三个纵向的bSizer要加入bSizer2中,实现四例的按钮组合
bSizer2.Add( bSizer3, 1, wx.EXPAND, 5 )#创建第四个布局BoxSizer 为 bSizer4,纵向的
bSizer4 = wx.BoxSizer( wx.VERTICAL )self.m_button5 = wx.Button( self, wx.ID_ANY, u"+", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button5.SetMinSize( wx.Size( 70,60 ) )bSizer4.Add( self.m_button5, 0, wx.ALL, 5 )self.m_button6 = wx.Button( self, wx.ID_ANY, u"8", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button6.SetMinSize( wx.Size( 70,60 ) )bSizer4.Add( self.m_button6, 0, wx.ALL, 5 )self.m_button7 = wx.Button( self, wx.ID_ANY, u"5", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button7.SetMinSize( wx.Size( 70,60 ) )bSizer4.Add( self.m_button7, 0, wx.ALL, 5 )self.m_button8 = wx.Button( self, wx.ID_ANY, u"2", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button8.SetMinSize( wx.Size( 70,60 ) )bSizer4.Add( self.m_button8, 0, wx.ALL, 5 )self.m_button18 = wx.Button( self, wx.ID_ANY, u"0", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button18.SetMinSize( wx.Size( 70,60 ) )bSizer4.Add( self.m_button18, 0, wx.ALL, 5 )bSizer2.Add( bSizer4, 1, wx.EXPAND, 5 )#创建第五个布局BoxSizer 为 bSizer5,纵向的
bSizer5 = wx.BoxSizer( wx.VERTICAL )self.m_button9 = wx.Button( self, wx.ID_ANY, u"-", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button9.SetMinSize( wx.Size( 70,60 ) )bSizer5.Add( self.m_button9, 0, wx.ALL, 5 )self.m_button10 = wx.Button( self, wx.ID_ANY, u"9", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button10.SetMinSize( wx.Size( 70,60 ) )bSizer5.Add( self.m_button10, 0, wx.ALL, 5 )self.m_button11 = wx.Button( self, wx.ID_ANY, u"6", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button11.SetMinSize( wx.Size( 70,60 ) )bSizer5.Add( self.m_button11, 0, wx.ALL, 5 )self.m_button12 = wx.Button( self, wx.ID_ANY, u"3", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button12.SetMinSize( wx.Size( 70,60 ) )bSizer5.Add( self.m_button12, 0, wx.ALL, 5 )self.m_button19 = wx.Button( self, wx.ID_ANY, u".", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button19.SetMinSize( wx.Size( 70,60 ) )bSizer5.Add( self.m_button19, 0, wx.ALL, 5 )bSizer2.Add( bSizer5, 1, wx.EXPAND, 5 )bSizer6 = wx.BoxSizer( wx.VERTICAL )self.m_button13 = wx.Button( self, wx.ID_ANY, u"<<", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button13.SetMinSize( wx.Size( 70,60 ) )bSizer6.Add( self.m_button13, 0, wx.ALL, 5 )self.m_button14 = wx.Button( self, wx.ID_ANY, u"*", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button14.SetMinSize( wx.Size( 70,60 ) )bSizer6.Add( self.m_button14, 0, wx.ALL, 5 )self.m_button15 = wx.Button( self, wx.ID_ANY, u"/", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button15.SetMinSize( wx.Size( 70,60 ) )bSizer6.Add( self.m_button15, 0, wx.ALL, 5 )self.m_button16 = wx.Button( self, wx.ID_ANY, u"=", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_button16.SetMinSize( wx.Size( 70,125 ) )bSizer6.Add( self.m_button16, 0, wx.ALL, 5 )bSizer2.Add( bSizer6, 1, wx.EXPAND, 5 )#将横向的bSizer2加入bSizer1中第二个格子中,第一个格式是编辑框,第二个格子是按钮组全布局
bSizer1.Add( bSizer2, 1, wx.EXPAND, 5 )self.SetSizer( bSizer1 )
self.Layout()
bSizer1.Fit( self )self.Centre( wx.BOTH )#析构函数 与 __init__相反,一个创造,一个毁灭
def __del__( self ):
pass
二、代码架构设计
1、将计算器运行起来
1)建工程目录
随便新增一个目录,将此目录取为GUIDEMO目录
使用pycharm ---file---Open 打开这个目录
在目录下新增一个Python Package目录,命名为:Calculator
2)复制图形界面Python代码
在Calculator下新增一个python文件MainFarme.py
将图形界面的python代码复制过来
没有安装wxPython库的,代码中的import wx 会提示红色波浪线,
使用命令安装:pip install wxpython
注意,复制过来的代码中,有异常代码,会运行报错,整理一下
找到self.SetSizeHintsSz改为:self.SetSizeHints
在Calculator下新增一个python文件runMain.py
在其中添加代码
import wx
from MainFarme import MyFrame1'''
新建一个类,继承MyFrame1,
'''
class newWindow(MyFrame1):pass'''
运行入口
添加wx对象
添加NewWindow对象
newWindow显示(show)
'''if __name__=='__main__':app = wx.App()win = newWindow(None)win.Show()app.MainLoop()
运行代码,出现了计算器窗口
此时,发现在。显示器中的字符未消失,且按钮响应事件未设置。
所以插入一拨wxFormBuilder的操作
一般我们写运行代码时,不直接使用MyFrame1创建对象,而是再用一个类继承MyFarme1。好处:就是在子类里修改代码不影响父类,如果我们调整图形界面,生成的新代码直接Copy过来用,无任何影响
2、添加按钮事件
回到wxFormBuilder点击按钮,在OjbectProperties下找到Events事件编辑,给OnButtonClick添加响应函数
如C按钮,添加响应函数OnClear
下面Bind方法就是绑定函数的方法
自动生成OnClear函数,里面有事件跳过的代码。
照模样将所有按钮都添加上事件如下。
将最新代码Copy到MainFarme.py中来
3、代码实现
之前我们做了newWindow继承MyFrame1的操作,是为了隔离图形界面修改,这算初步的封闭开发架构
如果是真实开发一个中大型项目,肯定不只是一个框体,所以有可能有很多个MyFrame文件与类,如果是都放在同一个目录下面,那么管理起来会很麻烦。
用目录分类管理代码文件,即使扩展再多的页面,也能条理清楚
mainFarme.py是图形界面代码,这里便不展示了
newWindow.py
#先继承MyFrame1,然后将所有按钮的点击事件覆盖,因为功能是要在这边实现
#定义了计算器算术式变量 self.formula_Text 计算结果self.result_Text
#实现的功能中使用到了re正则表达式,导入正则表达式,导入
import re #导入正则表达式
from MainFarme import MyFrame1 #导入计算器图形代码类
class NewWindow(MyFrame1):def __init__(self, parent):'''初始化:param parent:'''#计算器算术式self.formula_Text = ''#计算结果self.result_Text = ''super().__init__(parent)
按照逻辑与显示屏展示逻辑实现:
1)显示器展示
def set_Calculator_Text(self):'''设置显示器算式与计算结果:return:'''if self.result_Text != '':self.formula_Text += '\n' + self.result_Textself.m_textCtrl1.SetValue(self.formula_Text)
2)清空按钮功能
def clear_Calculator_Text(self):'''清空显示屏:return:'''self.result_Text = ''self.formula_Text = ''self.m_textCtrl1.SetValue('')
3)其他按钮实现 里面有使用到正则表达式,记录在最前面导入
def btn_Response(self, btn_value):'''实现按钮的功能:param btn_value: 按钮符号:return:'''if self.result_Text != '' and btn_value != '<<':self.clear_Calculator_Text()# 运算符operation = ('+', '-', '*', '/', '%')# 如果已有内容是以小数点开头的,在前面加 0if self.formula_Text.startswith('.'):self.formula_Text = '0' + self.formula_Text # 字符串可以直接用+来增加字符# 根据不同的按钮作出不同的反应if btn_value in '0123456789':# 按下 0-9 在 content 中追加self.formula_Text += btn_valueelif btn_value == '.':# 将 content 从 +-*/ 这些字符的地方分割开来lastPart = re.split(r'\+|-|\*|/|%', self.formula_Text)[-1]if '.' in lastPart:# 信息提示对话框returnelif len(lastPart) == 0:btn_value = '0' + btn_valueself.formula_Text += btn_valueelif btn_value == 'C':# 清除文本框self.formula_Text = ''elif btn_value == '<<':if self.result_Text != '':self.result_Text = ''self.formula_Text = self.formula_Text.split('\n')[0]self.formula_Text = self.formula_Text[:-1]elif btn_value == '=':try:# 对输入的表达式求值self.result_Text = str(eval(self.formula_Text))self.formula_Text += btn_valueexcept Exception as e:returnelif btn_value in operation:if self.formula_Text.endswith(operation):returnself.formula_Text += btn_valueself.set_Calculator_Text()
按钮逻辑实现完成后了,再实现按钮点击响应函数,子类实现覆盖父类响应函数
def OnClear(self, event):'''清空:param event::return:'''self.btn_Response('C')def OnSeven(self, event):'''数字7:param event::return:'''self.btn_Response('7')def OnFour(self, event):'''数字4:param event::return:'''self.btn_Response('4')def OnOne(self, event):'''数字1:param event::return:'''self.btn_Response('1')def OnMorethan(self, event):'''按钮%:param event::return:'''self.btn_Response('%')def OnAdd(self, event):'''按钮+:param event::return:'''self.btn_Response('+')def Oneight(self, event):'''数字8:param event::return:'''self.btn_Response('8')def OnFive(self, event):'''数字5:param event::return:'''self.btn_Response('5')def OnTwo(self, event):'''数字2:param event::return:'''self.btn_Response('2')def OnZero(self, event):'''数字0:param event::return:'''self.btn_Response('0')def OnReduce(self, event):'''按钮-:param event::return:'''self.btn_Response('-')def OnNine(self, event):'''数字9:param event::return:'''self.btn_Response('9')def Onsix(self, event):'''数字6:param event::return:'''self.btn_Response('6')def Onthree(self, event):'''数字3:param event::return:'''self.btn_Response('3')def OnDecimal(self, event):'''小数点。:param event::return:'''self.btn_Response('.')def OnDel(self, event):'''退格 <<:param event::return:'''self.btn_Response('<<')def OnRide(self, event):'''按钮*:param event::return:'''self.btn_Response('*')def OnExcept(self, event):'''按钮/:param event::return:'''self.btn_Response('/')def OnEqualto(self, event):'''按钮=:param event::return:'''self.btn_Response('=')
4、运行计算器
在runMain.py文件里编写运行代码i
import wx
from Calculator.manage.newWindow import NewWindow'''
运行入口
添加wx对象
添加NewWindow对象
newWindow显示(show)
'''if __name__=='__main__':app = wx.App()win = NewWindow(None)win.Show()app.MainLoop()
运行
三、测试计算器逻辑
5+2=
2+2*4=
1+3+56=
1111+2222=
9/3=
123123123 C
还可以做很多测试,有很多BUG
不过本文结束啦
代码打包下载路径
wxFormBuilder+wxPython+Python实现的简易计算器小项目代码-Python文档类资源-CSDN下载
wxFormBuilder + wxPython手撸丑陋计算器相关推荐
- python手撸桌面计算器
网上有一些许多关于计算器的源码,但我似乎不太care 一直寻思着自己手撸一个才有意思,于是这就开始了 实现功能: 1.基本的两个数 +-x÷ 运算以及取反,百分之,平方等 2.支持连续运算 3.暂不支 ...
- php 辗转相除法,手撸golang 基本数据结构与算法 最大公约数 欧几里得算法/辗转相除法...
手撸golang 基本数据结构与算法 最大公约数 欧几里得算法/辗转相除法 缘起 最近阅读<>([日]石田保辉:宫崎修一) 本系列笔记拟采用golang练习之 欧几里得算法欧几里得算法(又 ...
- 在用安全框架前,我想先让你手撸一个登陆认证
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 转自:RudeCrab, 链接:blog.csdn.net ...
- 清华大一Python作业太难上热榜!只上3节课,手撸AI算法,网友:离本科毕设只差一篇万字论文...
点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 金磊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 太难了! ...
- 如何手撸一个较为完整的RPC框架
[文章作者/来源]一个没有追求的技术人/https://sourl.cn/sJ4Brp 缘 起 最近在公司分享了手撸RPC,因此做一个总结. 概 念 篇 RPC 是什么? RPC 称远程过程调用(Re ...
- 10分钟手撸极简版ORM框架!
最近很多小伙伴对ORM框架的实现很感兴趣,不少读者在冰河的微信上问:冰河,你知道ORM框架是如何实现的吗?比如像MyBatis和Hibernte这种ORM框架,它们是如何实现的呢? 为了能够让小伙伴们 ...
- 【手撸RPC框架】SpringBoot+Netty4实现RPC框架
[手撸RPC框架]SpringBoot+Netty4实现RPC框架 线程模型1:传统阻塞 I/O 服务模型 模型特点: 采用阻塞IO模式获取输入的数据 每个链接都需要独立的线程完成数据的输入,业务处理 ...
- mysql 原生 添加数据_手撸Mysql原生语句--增删改查
mysql数据库的增删改查有以下的几种的情况, 1.DDL语句 数据库定义语言: 数据库.表.视图.索引.存储过程,例如CREATE DROP ALTER SHOW 2.DML语句 数据库操纵语言: ...
- .Net Core手撸一个基于Token的权限认证
说明 权限认证是确定用户身份的过程.可确定用户是否有访问资源的权力 今天给大家分享一下类似JWT这种基于token的鉴权机制 基于token的鉴权机制,它不需要在服务端去保留用户的认证信息或者会话信息 ...
- .NET手撸绘制TypeScript类图——下篇
.NET手撸绘制TypeScript类图--下篇 在上篇的文章中,我们介绍了如何使用 .NET解析 TypeScript,这篇将介绍如何使用代码将类图渲染出来. 类型定义渲染 不出意外,我们继续使用 ...
最新文章
- 高级Lucene查询示例
- word删除所有的回车、空格
- css中的大于号是什么意思 有何作用
- Bert遇到文本分类:如何用好Bert这把刀
- iZotope RX 9 Advanced for Mac - 高级音频修复软件
- python可迭代对象 迭代器生成器_第八章 Python可迭代对象、迭代器和生成器-阿里云开发者社区...
- mac下安装win7虚拟机
- MPB:林科院袁志林组-树木共生真菌菌株纯化及快速鉴定方法
- 交警罚没系统数据一致性问题
- DB2 create database报错SQL1036C,Could not init GLFH lock file
- Keil编译后Code RO Data Rw Data ZI的含义
- .NET MVC第九章、Web Api Json序列化与反序列化
- jlink修复固件教程
- opencv-python 读取视频时如何判断读取到最后一张
- 【ADS867x】14 位 500kSPS 4/8 通道 ADC 简介及驱动应用示例
- linux su命令参数及用法详解--linux切换用户命令
- 仿SDWebImage
- h5发送短信以及判别用户浏览器版本
- Leetcode各种题型题目+思路+代码(共176道题)
- w ndows10故障如何重新进入,天正建筑T20常见问题
热门文章
- Intel 实习mentor布置问题1
- 【计算机基础】解决Win10电脑主机前面的耳机插口没声音的问题
- matlab命令查找图片,Matlab 显示图片和SubPlot命令
- vpp之node节点分析二: qs类型
- videos player.php_基于vue-video-player自定义播放器的方法
- 基于Web的仓库管理系统的设计与实现
- 软考计算机网络与最大流量,软考程序员考点计算机网络之性能
- linux 编译 pascal,免费开源的Pascal编译器 GNU Pascal
- OpenCV2.3.1+VS2005配置方法
- win10 安装IIS