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手撸丑陋计算器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 矩阵计算器+求线性代数n阶行列式代码
- 下一篇: 【Java】HashMap源码(1.7)