Python_GUI學習筆記(3)wxPython的簡單介面設計
第一次接觸到wxpython,在網上找到一個簡單的介面顯示程式碼,複製到spyder3編輯中進行執行出現錯誤,(“module 'wx' has no attributte 'App'”),但在python3.6的IDLE編輯器上執行沒有錯誤。具體程式如下:
import wx
app = wx.App()
frame = wx.Frame(None,title="my GUI")
frame.Show(1)
app.MainLoop()
於是在網上找到一些解決方法:
1)wx.py 檔名與外掛wx 重名了;【命名py指令碼時,不要與python預留字,模組名等相同;刪除該庫的.pyc檔案(因為py指令碼每次執行時均會生成.pyc檔案;在已經生成.pyc檔案的情況下,若程式碼不更新,執行時依舊會走pyc,所以要刪除.pyc檔案),重新執行程式碼;或者找一個可以執行程式碼的環境,拷貝替換當前機器的.pyc檔案即可
解決:
把wx.py 改成 editor.py 執行成功彈出一個文字框,如附件截圖:
D:\ProgramFiles64\Anaconda36\Lib\site-packages\IPython\terminal\pt_inputhooks\wx.py檔案修改為editor.py,再執行。】
2)有的說是版本問題;
我按方法1修改了之後,還是沒有成功,後來我將spyder重啟,並且所有設定恢復預設之後,再執行又沒有錯誤,具體原因在哪裡我還是沒有搞清楚。
下面我們來實現簡單介面設計:
最小的wxpython程式,叫它hello world程式吧。功能就是產生一個視窗,就像是我們VC中新建的一個單文件的MFC類似,不過沒有選單什麼的,只有一個框架視窗。其實嚴格來說,wxpython不叫這個為視窗,而是“frame”。實現
一>import wx
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, "Hello World")
frame.Show()
app.MainLoop()
二>import wx
app = wx.App()
frame = wx.Frame(None, -1, "Hello World")
frame.Show()
app.MainLoop()
三>import wx
class MyApp(wx.App):
def OnInit(self):
frame=wx.Frame(parent=None,title='Hello wxpython')
frame.Show()
return True
app=MyApp()
app.MainLoop()
【下面部分轉載博主:http://blog.sina.com.cn/s/blog_4b5039210100eykc.html】
可以看到,frame上面什麼都沒有。但所謂麻雀雖小,五臟俱全,從這個最小的程式我們就能看出一個wxpython程式都包含哪些東西:
1 匯入wxpython庫,或者裡面的方法( import wx)
2 建立一個應用類的子類(繼承於wxpython中的App類,class MyApp(wx.App):)
3 定義應用子類初始化方法(OnInit())
4 建立應用類的例項
5 進入應用類的訊息迴圈 MainLoop
我們主要看一下,應用類的OnInit函式,在這個初始化方法中,我們生成了一個wx.frame物件的一個例項,因為這個程式比較簡單,所以這個過程放到了OnInit方法中,一般情況下,我們都是定義一個繼承於wx..Frame的子類(類似於MyApp一樣),這個我們在以後會經常看到。
還有一點,我們在App類初始化沒有呼叫__init__()這個方法,這意味著我們這個子類建立的過程中,按照類的繼承性,這個方法會被自動呼叫。當然我們可以重新定義這個方法,但是一定要在子類中呼叫一下基類的__init__()方法。例如:
class App(wx.App):
def __init__(self):
wx.App.__init__(self)
#Do something here.....
最後建立應用類例項和進入訊息迴圈和Tkinter差不多,就不說了。
上面例子只是為了說明wxpython的基本用法,但是那個程式碼其實擴充套件性很差,那麼,作為一般wxpython程式應該怎麼寫呢?我們看下面的程式碼
#!/usr/bin/env Python
“”” hello.py is a starting point for a wxpython program”””
import wx
class Frame(wx.Frame):
pass
class App(wx.App):
def OnInit(self):
self.frame=Frame(parent=None,title='Hello wxpython')
self.frame.Show()
self.SetTopWindow(self.frame)
return True
if __name__=='__main__':
app=App()
app.MainLoop()
第一行是註釋行,在windows中不是必須的,但是在linux中需要有,它告訴作業系統python直譯器在什麼地方,有了這個以後,我們就可以在linux命令列裡直接輸入檔名運行了。雖然windows中這個不是必須的,但是為了相容性跨平臺,這個一般還是要有的。
第二行的三引號所夾內容就不說了。
下面第一個類是繼承於wx..Frame的frame類。這裡我們什麼沒做,其實在這裡我們可以做很多事,比如建立一些元件(按鈕,文字框等待),這樣把frame單獨拿出來,為了使程式更清晰可讀。
第二個類是繼承於wx..App的App類。和第一個程式類似,只不過這裡的frame換成了呼叫Frame,例項化得物件。
self.SetTopWindow(self.frame),這個其實是把self.frame作為了主frame,因為一個程式中可能會有多個frame。通過這個可以設定哪個frame是最頂層的主frame。
最後的if語句就是這個程式的入口。
下面,我們把上面的例子稍微擴充一點。
#!/usr/bin/env python
""" Hello,wxPython program."""
import wx #import the wxPackage
class Frame(wx.Frame):
"""Frame class that display an image."""
def __init__(self,image,parent=None,id=-1,
pos=wx.DefaultPosition,
title='Hello wxPython'):
temp=image.ConvertToBitmap() #Displaying the image
size=temp.GetWidth(),temp.GetHeight()
wx.Frame.__init__(self,parent,id,title,pos,size)
self.bmp=wx.StaticBitmap(parent=self,bitmap=temp)
class App(wx.App):
"""Application class."""
def OnInit(self):
image=wx.Image('wxpython.jpg',wx.BITMAP_TYPE_JPEG)
self.frame=Frame(image)
self.frame.Show()
self.SetTopWindow(self.frame)
return True
def main():
app=App()
app.MainLoop()
if __name__=='__main__':
main()
實現是在frame上顯示一張照片。結果為: