目录

前言

一、设计计算器图形界面

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手撸丑陋计算器相关推荐

  1. python手撸桌面计算器

    网上有一些许多关于计算器的源码,但我似乎不太care 一直寻思着自己手撸一个才有意思,于是这就开始了 实现功能: 1.基本的两个数 +-x÷ 运算以及取反,百分之,平方等 2.支持连续运算 3.暂不支 ...

  2. php 辗转相除法,手撸golang 基本数据结构与算法 最大公约数 欧几里得算法/辗转相除法...

    手撸golang 基本数据结构与算法 最大公约数 欧几里得算法/辗转相除法 缘起 最近阅读<>([日]石田保辉:宫崎修一) 本系列笔记拟采用golang练习之 欧几里得算法欧几里得算法(又 ...

  3. 在用安全框架前,我想先让你手撸一个登陆认证

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 转自:RudeCrab, 链接:blog.csdn.net ...

  4. 清华大一Python作业太难上热榜!只上3节课,手撸AI算法,网友:离本科毕设只差一篇万字论文...

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 金磊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 太难了! ...

  5. 如何手撸一个较为完整的RPC框架

    [文章作者/来源]一个没有追求的技术人/https://sourl.cn/sJ4Brp 缘 起 最近在公司分享了手撸RPC,因此做一个总结. 概 念 篇 RPC 是什么? RPC 称远程过程调用(Re ...

  6. 10分钟手撸极简版ORM框架!

    最近很多小伙伴对ORM框架的实现很感兴趣,不少读者在冰河的微信上问:冰河,你知道ORM框架是如何实现的吗?比如像MyBatis和Hibernte这种ORM框架,它们是如何实现的呢? 为了能够让小伙伴们 ...

  7. 【手撸RPC框架】SpringBoot+Netty4实现RPC框架

    [手撸RPC框架]SpringBoot+Netty4实现RPC框架 线程模型1:传统阻塞 I/O 服务模型 模型特点: 采用阻塞IO模式获取输入的数据 每个链接都需要独立的线程完成数据的输入,业务处理 ...

  8. mysql 原生 添加数据_手撸Mysql原生语句--增删改查

    mysql数据库的增删改查有以下的几种的情况, 1.DDL语句 数据库定义语言: 数据库.表.视图.索引.存储过程,例如CREATE DROP ALTER SHOW 2.DML语句 数据库操纵语言: ...

  9. .Net Core手撸一个基于Token的权限认证

    说明 权限认证是确定用户身份的过程.可确定用户是否有访问资源的权力 今天给大家分享一下类似JWT这种基于token的鉴权机制 基于token的鉴权机制,它不需要在服务端去保留用户的认证信息或者会话信息 ...

  10. .NET手撸绘制TypeScript类图——下篇

    .NET手撸绘制TypeScript类图--下篇 在上篇的文章中,我们介绍了如何使用 .NET解析 TypeScript,这篇将介绍如何使用代码将类图渲染出来. 类型定义渲染 不出意外,我们继续使用  ...

最新文章

  1. 高级Lucene查询示例
  2. word删除所有的回车、空格
  3. css中的大于号是什么意思 有何作用
  4. Bert遇到文本分类:如何用好Bert这把刀
  5. iZotope RX 9 Advanced for Mac - 高级音频修复软件
  6. python可迭代对象 迭代器生成器_第八章 Python可迭代对象、迭代器和生成器-阿里云开发者社区...
  7. mac下安装win7虚拟机
  8. MPB:林科院袁志林组-树木共生真菌菌株纯化及快速鉴定方法
  9. 交警罚没系统数据一致性问题
  10. DB2 create database报错SQL1036C,Could not init GLFH lock file
  11. Keil编译后Code RO Data Rw Data ZI的含义
  12. .NET MVC第九章、Web Api Json序列化与反序列化
  13. jlink修复固件教程
  14. opencv-python 读取视频时如何判断读取到最后一张
  15. 【ADS867x】14 位 500kSPS 4/8 通道 ADC 简介及驱动应用示例
  16. linux su命令参数及用法详解--linux切换用户命令
  17. 仿SDWebImage
  18. h5发送短信以及判别用户浏览器版本
  19. Leetcode各种题型题目+思路+代码(共176道题)
  20. w ndows10故障如何重新进入,天正建筑T20常见问题

热门文章

  1. Intel 实习mentor布置问题1
  2. 【计算机基础】解决Win10电脑主机前面的耳机插口没声音的问题
  3. matlab命令查找图片,Matlab 显示图片和SubPlot命令
  4. vpp之node节点分析二: qs类型
  5. videos player.php_基于vue-video-player自定义播放器的方法
  6. 基于Web的仓库管理系统的设计与实现
  7. 软考计算机网络与最大流量,软考程序员考点计算机网络之性能
  8. linux 编译 pascal,免费开源的Pascal编译器 GNU Pascal
  9. OpenCV2.3.1+VS2005配置方法
  10. win10 安装IIS