使用WxPython进行Win32下Python编程
最近在研究wxpython,需要在win32下編程。
1
另一種可供Python使用的GUI工具包叫做wxPython。目前這個工具對于Python環境來說還是陌生的,但正在Python開發者中間快速地流行起來。
wxPython是Python擴展模塊,它封裝了wxWindows C++類庫。
wxPython是一個為Python提供的交叉平臺GUI框架工具,它在Windows平臺上相當成熟。它是基于流行的wxWindows C++框架的Python,為GUI
開發者提供了一種有吸引力的替代工具。
wxWindows
wxWindows是一個自由C++編程框架,被設計用來實現跨平臺編程。wxWindows 2.0支持Windows 3.1/95/98/NT,Unix下支持
GTK/Motif/Lesstif,還有正在開發中的Mac版本。其它系統正在考慮中。
wxWindows是一套庫函數,允許C++應用程序只需要微量的源代碼改動,就可在幾種不同類型的機構上編譯和運行。每一種支持的GUI都有一
個對應的庫( 象Motif或Windows)。同時為了實現GUI功能提供了通用的API,還為了處理一些通常要用到的操作系統設備提供了功能,應用程序
可以根據需要使用或替換,這樣就會節省大量的編碼工作。基本數據結構,象字符串,鏈表,和哈希表也提供了。
控件的本地版本,通用對話框,和其它的窗口類型被用在支持它們的平臺上。對于其它的平臺,相適應的替代品使用wxWindows自身來生成
。例如,在W in32平臺上,使用了本地的列表控件,但是在GTK,具有相似功能的通用列表控件則是使用wxWindows類庫創建的。
有經驗的Windows程序員對于wxWindows對象模型會感到象是在家一樣。類和原則的許多地方都很相似。例如,多文檔界面,用GDI對象,如
刷子,筆,在上下文設置上繪圖,等等。
wxWdinws + Python = wxPython
wxPython是一個Python擴展模塊,它提供了一套從wxWindows庫到Python語言的綁定。換句話說,擴展模塊允許Python程序員創建wxW
indows類的實例,并且調用這些類的方法。
wxPython擴展模塊試圖近可能的將wxWindows的類的層次也鏡像下來。這就是說在wxPython中有一個wxFrame的類,看上去,聞上去,嘗上
去和行為上幾乎同C ++版本中的wxFrame一樣。
wxPython與C++版本如此接近,這樣wxPython文檔的大多數實際上是對C++文檔中,wxPython與之不同地方的注解。其中還包含了一系列的
例子程序,和一系列幫助程序員開始使用w xPython的文檔頁
2
哪里可以得到wxPython
wxPython的最新版本可以在http://alldunn.com/wxPython/上找到。你可以從這個站點下載一個Win32系統的自安裝軟件,其中包含一個已
經生成好的擴展模塊,H TML幫助格式文檔,和一組示例程序。
也可以從這個站點獲得Linux RPM,wxPython源碼,原始的HTML文檔,和其它站點的鏈接,郵件列表,wxPython FAQ,等等。
如果你想自已從源代碼創建wxPython,你也需要wxWindows源代碼,可以從http://www.wxwindows.org/得到。
下一步去哪里?
實踐證明,學習的最好方法就是動手,接著做實驗,觀察得到的結果。所以你應該下載和安裝wxPython,啟動你常用的文本編輯器,準備
執行在下面幾節所讀到的東西。
一個簡單的例子
應該對下面的小wxPython程序進行熟悉,當讀到跟著的解釋時,可以回過頭來進行參考:
from wxPython.wx import *
class MyApp(wxApp):
def OnInit(self):
frame = wxFrame(NULL, -1, "Hello from wxPython")
frame.Show(true)
self.SetTopWindow(frame)
return true
app = MyApp(0)
app.MainLoop()
一個基本的wxPython程序要做的第一件事情就是導入整個wxPython庫,使用 from wxPython import * 語句。這是編wxPython程序的通常習
慣,但是你可以根據需要明確地執行更多限制的導入。
每一個wxPython應用程序需要從wxApp派生出一個類,并且為其提供一個OnInit 方法。框架(即窗口)會調用這個方法作為自身初始化序
列的一部分。Oninit通常是用來創建窗口,和對于程序開始運行完全必需的操作。在例子中,你創建了一個沒有父親的框架,標題是“Hello
from wxPython ”,然后顯示它。我們也可以在它的構造函數中為框架指定位置和大小,但是因為沒有,所以這里使用了缺省值。OnInit方法
的最后兩行可能對于所有應用程序來說都是一樣的。SetTopWindow方法告訴wxWindows ,這個框架是應用程序主框架其中之一(在這個例子中
只有一個),并且你返回true來表明成功。當所有項層窗口實關閉,應用程序結束。
腳本的最后兩行可能又是對于所有的wxPython應用程序是一樣的。你創建了一個應用程序類的實例,并且調用它的MainLoop方法。
MainLoop是應用程序的心臟:在這里事情被處理,并且被發送到各個窗口,當最后一個窗口關閉后,它返回。幸運的是,wxWindows對你屏蔽了
各種GUI工具包在事件處理上的不同。
?
3
大多數情況下,你會想要定制應用程序的主框架,所以使用普通的wxFrame是不夠的。你可能希望,從wxFrame派生出自已的類進行定制。下一
個例子定義了一個框架類,并且在應用程序中的O nInit方法中創建了一個實例。注意除了在OnInit中創建的類的名字,MyApp代碼的其它部分
同以前的例子是一樣的。
from wxPython.wx import *
ID_ABOUT = 101
ID_EXIT = 102
class MyFrame(wxFrame):
def __init__(self, parent, ID, title):
wxFrame.__init__(self, parent, ID, title,wxDefaultPosition, wxSize(200, 150))
self.CreateStatusBar()
self.SetStatusText("This is the statusbar")
menu = wxMenu()
menu.Append(ID_ABOUT, "&About","More information about this program")
menu.AppendSeparator()
menu.Append(ID_EXIT, "E&xit", "Terminate the program")
menuBar = wxMenuBar()
menuBar.Append(menu, "&File");
self.SetMenuBar(menuBar)
class MyApp(wxApp):
def OnInit(self):
frame = MyFrame(NULL, -1, "Hello from wxPython")
frame.Show(true)
self.SetTopWindow(frame)
return true
app = MyApp(0)
app.MainLoop()
這個例子顯示了一些wxFrame內建的一些功能。例如,為框架創建一個狀態條只要簡單地調用一個方法。框架本身會自動地管理它的位置,
大小,和繪制。另一方面,如果你想定制狀態條,從你自已的wxStatusBar派生類創建實例,并將其附加到框架上。
在這個例子中也演示了創建一個簡單的菜單條和一個下拉菜單。期待的菜單功能全部都支持:層疊子菜單,可核選的項,彈出菜單等等;
你要做的只是創建一個菜單對象,向它追加菜單項。菜單項可以是象這里顯示的文本,或其它的菜單。每一項你可以有選擇地指定一些簡單的
幫助性文本,就象我們所做的。當菜單項被選中,這些文本會自動地顯示在狀態條上。
?
4
在wxPython中的事件上一個例子沒有做的一件事情就是:展示如何讓菜單自動做一些事情。如果你運行這個例子,并且從菜單中選中Exit,
什么都沒有發生。下一個例子改正了這個小問題。
為了在wxPython中處理事件,任何方法(或同樣方式的獨立函數)都可以使用工具包中的幫助性函數與任意事件相連。wxPython也提供了
一個w xEvent 類,和一整串派生類,包含了事件的細節。每次當發生一個事件,一個方法被調用,一個從wxEvent 派生的對象被做為一參數傳
遞,事件對象的實際類型要依賴于事件的類型。wxSizeEvent用于當窗口改變大小,wxCommandEvent用于菜單選擇和按鈕點擊,w xMouseEvent
用于(可以猜到)鼠標的移動,等等。
為了解決上一個例子中的小問題,你要做的就是,在MyFrame構造函數中增加兩行,并且增加處理事件的一些方法。我們也演示了一個通用
對話框,w xMessageDialog。下面就是代碼。
from wxPython.wx import *
ID_ABOUT = 101
ID_EXIT = 102
class MyFrame(wxFrame):
def __init__(self, parent, ID, title):
wxFrame.__init__(self, parent, ID, title,wxDefaultPosition, wxSize(200, 150))
self.CreateStatusBar()
self.SetStatusText("This is the statusbar")
menu = wxMenu()
menu.Append(ID_ABOUT, "&About","More information about this program")
menu.AppendSeparator()
menu.Append(ID_EXIT, "E&xit", "Terminate the program")
menuBar = wxMenuBar()
menuBar.Append(menu, "&File");
self.SetMenuBar(menuBar)
EVT_MENU(self, ID_ABOUT, self.OnAbout)
EVT_MENU(self, ID_EXIT, self.TimeToQuit)
def OnAbout(self, event):
dlg = wxMessageDialog(self, "This sample program shows off\n"
"frames, menus, statusbars, and this\n""message dialog.",
"About Me", wxOK | wxICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def TimeToQuit(self, event):
self.Close(true)
class MyApp(wxApp):
def OnInit(self):
frame = MyFrame(NULL, -1, "Hello from wxPython")
frame.Show(true)
self.SetTopWindow(frame)
return true
app = MyApp(0)
app.MainLoop()
在這里調用的EVT_MENU函數是一個幫助性函數,是為了將事件與方法連在一起。有時候,如果你將函數調用翻譯成英語,它可以幫助我們
理解發生了什么。第一個說的是,“對于任一個菜單項選中事件,發送窗口本身和一個ID_ABOUT的ID號,調用self.OnAbout方法。”
有很多EVT_*幫助性函數,所有的都對應某個事件類型,或事件。下面將常用的一些事件列出。
請參閱wxPython文檔了解更多的細節。
常見wxPython事件函數 事件函數事件描述
EVT_SIZE
由于用戶干預或由程序實現,當一個窗口大小發生改變時發送給窗口。
EVT_MOVE
由于用戶干預或由程序實現,當一個窗口被移動時發送給窗口。
EVT_CLOSE
當一個框架被要求關閉時發送給框架。除非關閉是強制性的,否則可以調用event.Veto(true)來取消關閉。
EVT_PAINT
無論何時當窗口的一部分需要重繪時發送給窗口。
EVT_CHAR
當窗口擁有輸入焦點時,每產生非修改性(Shift鍵等等)按鍵時發送。
EVT_IDLE
這個事件會當系統沒有處理其它事件時定期的發送。
EVT_LEFT_DOWN
鼠標左鍵按下。
EVT_LEFT_UP
鼠標左鍵抬起。
EVT_LEFT_DCLICK
鼠標左鍵雙擊。
EVT_MOTION
鼠標在移動。
EVT_SCROLL
滾動條被操作。這個事件其實是一組事件的集合,如果需要可以被單獨捕捉。
EVT_BUTTON
按鈕被點擊。
EVT_MENU
菜單被選中
5
用Python創建一個Doubletalk瀏覽器
Ok, 現在讓我們做些有用的東西,用這種方法學習更多關于wxPython框架的知識。就象其它的GUI工具包所展示的,我們將創建一個小型的
應用程序,圍繞著Doubletalk類庫(它允許瀏覽和編輯交易)。
MDI框架
我們打算實現一個多文檔界面(譯注,即MDI),子框架除了為獨立的“文檔”外,其中還包含著交易數據的不同視圖。如同前面的例子,
要做的第一件事就是創建一個應用程序類,并且在它的O nInit方法中創建一個主框架:
from wxPython.wx import *
class DoubleTalkBrowserApp(wxApp):
def OnInit(self):
frame = MainFrame(NULL)
frame.Show(true)
self.SetTopWindow(frame)
return true
app = DoubleTalkBrowserApp(0)
app.MainLoop()
因為我們正在使用MDI,所以需要一個特別的類用來做為框架的基本類。這里的給出主程序框架的初始化方法的代碼:
class MainFrame(wxMDIParentFrame):
title = "Doubletalk Browser - wxPython Edition"
def __init__(self, parent):
wxMDIParentFrame.__init__(self, parent, -1, self.title)
self.bookset = None
self.views = []
if wxPlatform == ’__WXMSW__’:
self.icon = wxIcon(’chart7.ico’, wxBITMAP_TYPE_ICO)
self.SetIcon(self.icon)
# 創建一個狀態條,在右邊顯示時間和日期
sb = self.CreateStatusBar(2)
sb.SetStatusWidths([-1, 150])
self.timer = wxPyTimer(self.Notify)
self.timer.Start(1000)
self.Notify()
menu = self.MakeMenu(false)
self.SetMenuBar(menu)
menu.EnableTop(1, false)
EVT_MENU(self, ID_OPEN, self.OnMenuOpen)
EVT_MENU(self, ID_CLOSE, self.OnMenuClose)
EVT_MENU(self, ID_SAVE, self.OnMenuSave)
EVT_MENU(self, ID_SAVEAS,self.OnMenuSaveAs)
EVT_MENU(self, ID_EXIT, self.OnMenuExit)
EVT_MENU(self, ID_ABOUT, self.OnMenuAbout)
EVT_MENU(self, ID_ADD, self.OnAddTrans)
EVT_MENU(self, ID_JRNL, self.OnViewJournal)
EVT_MENU(self, ID_DTAIL, self.OnViewDetail)
EVT_CLOSE(self, self.OnCloseWindow)
很明顯,我們沒有展示全部的代碼,但是隨著我們一點一點地學習,我們將最終將其變得完整。
注意,使用wxMDIParentFrame作為MainFrame的基類。通過使用這個類,你會自動地獲得為實現MDI應用程序的所有需要的東西,不需要關
心在外表后面發生了什么。wxMDIParentFrame 類有著與wxFrame類同樣的接口,只是擁有一些額外的方法。通常將一個單文檔接口程序改為一
個多文檔程序只是象改變應用程序派生類的基類一樣容易。對于wxMDIParentFrame 類,存在相對應的wxMDIChildFrame類,用于作文檔窗口,
在后面就會看到。如果你需要處理MDI父窗口的客戶區域(或背景區域),你可以使用 wxMDIClientWindow類。你可以使用它來在所有子窗口的
后面放置一個背景圖像。
在文件對話框成功完成之后,要做的第一件事就是詢問對話框被選中的路徑名是什么,然后使用這個路徑來修改框架的標題,然后打開
一個BookSet文件。
看一下后面一行。它重新使BookSet菜單有效,因為現在已經存在一個打開文件了。它實際是兩行語句合成一句,相當于這兩行:
menu = self.GetMenuBar()
menu.EnableTop(1, true)
因為當用戶打開一個文件時,讓他們確實地看到一些東西是有意義的,你應該創建并且顯示其中一個視圖,用上面的OnMenuOpen處理函數
中最后幾行代碼。在下面,我們會看到。
wxListCtrl
日志視圖是由wxListCtrl組成,其中每一個交易都有一個單行的小計。這個控件放置在wxMDIChildFrame中,并且因為它是框架中唯一的東
西,所以不用擔心設置或維護大小,框架會自動維護它。(不幸地是,因為某些平臺在不同的時間發送第一個改變大小(r esize)事件,有時
候窗口顯示時,它的子窗口大小會不正確。)
class JournalView(wxMDIChildFrame):
def __init__(self, parent, bookset, editID):
wxMDIChildFrame.__init__(self, parent, -1, "")
self.bookset = bookset
self.parent = parent
tID = wxNewId()
self.lc = wxListCtrl(self, tID, wxDefaultPosition,
wxDefaultSize, wxLC_REPORT)
## Forces a resize event to get around a minor bug...
self.SetSize(self.GetSize())
self.lc.InsertColumn(0, "Date")
self.lc.InsertColumn(1, "Comment")
self.lc.InsertColumn(2, "Amount")
self.currentItem = 0
EVT_LIST_ITEM_SELECTED(self, tID, self.OnItemSelected)
EVT_LEFT_DCLICK(self.lc, self.OnDoubleClick)
menu = parent.MakeMenu(true)
self.SetMenuBar(menu)
EVT_MENU(self, editID, self.OnEdit)
EVT_CLOSE(self, self.OnCloseWindow)
self.UpdateView()
轉載于:https://www.cnblogs.com/yd1227/archive/2009/07/29/1534512.html
總結
以上是生活随笔為你收集整理的使用WxPython进行Win32下Python编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [原创]红马版验证码实现(中文+变形+噪
- 下一篇: ASP.NET 2.0中使用自定义pro