wxPython介绍+一个实用的例子
1. wxPython简介
wxPython是wxWidget的库的一个python的封装。提供了一些库和一些工具。
这样wxPython即有python语言的优点: 语法强悍,少写了不少代码:)
也有wxWidget图形库的优点: 直接拉控件到大概位置就行了,不需要去调整控件的对齐,也不需要关心gui界面是否支持各种分辨率的桌面。而且界面都是可以运行时切换,只要写很少的切换代码。跨平台的图形库...
后悔,我怎么以前会用vb开发gui的 -_-!。
缺点,网上资料还比较少。而且在线文档都是英文的。不过如果英文好的话,到真的无所谓,因为wxPython的安装包本身提供的工具和资料也足够多,足够好了。
2. 开发入门 我使用ultraedit作为编辑器,wxPython自带的XRCed作为编辑xrc文件(一种xml格式的资源文件,类似于VC6中的RC文件)。
文档主要参考wxPython自带的在线文档和demo代码。不过关于如何使用xrc文件设计gui,wxPython自带的资料似乎还不够详细,这也是我写本文的原因。
通常情况下google"cvs def wxpython相关的关键字"可以快速找到开源的源代码参考。
如果这些例子还不够的话,就参考我的程序吧,这是一个商用程序的原型,我相信该程序的内容已经足够丰富了,应该比网上的一些wxPython教程中的hello world程序更有借鉴意义。
3. 源代码 两个文件,main.py是主程序,main.xrc是资源文件。只要安装了了python和wxpython,然后将这两个文件放在同一个目录中,运行main.py就可以了。
------------------------main.py-----------------------begin
################################################################################## #General: # read http://wiki./index.cgi/UsingXmlResources for more information about how to use xrc # #Problems: # google "(class 'wxMenuBar') not found ", visit http://aspn./ASPN/Mail/Message/wxPython-users/2242126 ( wxGlade's problem?) # google "TypeError: OnExit() takes exactly 2 arguments (1 given)" and visit http://www./irc-logs/gnue-public.log.2003-02-26 (wxPython's problem?) #
we *donot* want sash in splitter window to disappear. google
"wxSplitterEvent" , get "The sash was double clicked. The default
behaviour is to unsplit the window when this happens (unless *the
minimum pane size has been set to a value greater than zero*, yes it is
what we do in xrc)", # #Naming conventions: # class._var1 =
class shared variable (like static class data member in C++, BTW: see
python online help for python's private variables's naming conventions ) # class.CapitalizeEveryWord = class method # class.instance_data_member = instance's data member (like public data member in C++) # m_file_shared_variables = variables prefixed with "m_" are shared in a file # g_global_shared_variables = variables prefixed with "g_" are global variables ##################################################################################
from wxPython.wx import * from wxPython.xrc import * import sys
#the New Job dialog class dlgNew: def __init__(self,ctrl): assert(ctrl<>None) self.ctrl=ctrl self.idc_textmode_txt=self.ctrl.FindWindowById(XRCID("idc_textmode_txt")) assert(self.idc_textmode_txt<>None) self.idc_new_runnow=self.ctrl.FindWindowById(XRCID("idc_new_runnow")) assert(self.idc_new_runnow) self.idc_new_jobname=self.ctrl.FindWindowById(XRCID("idc_new_jobname")) assert(self.idc_new_jobname<>None) self.MessageMap(self.ctrl) def __del__(self): #self.ctrl.Destroy() pass def MessageMap(self,ctrl): EVT_BUTTON(ctrl, XRCID("idc_new_ok"), self.OnOK) EVT_BUTTON(ctrl, XRCID("idc_new_cancel"), self.OnCancel) EVT_BUTTON(ctrl, XRCID("idc_new_apply"), self.OnApply) def OnOK(self,event): if self.Validate(): self.OnApply(event) self.ctrl.Close(True) else: # report error pass def OnCancel(self,event): self.ctrl.Close(True) def OnApply(self,event): #save job #if needed, submit it now if self.idc_new_runnow.IsChecked(): pass def Validate(self): try: if self.idc_textmode_txt.GetValue()==None: assert(0) raise if self.idc_new_jobname.GetValue()==None: assert(0) raise if not self.IsCmdValid(self.idc_textmode_txt.GetValue()): assert(0) raise return True except: return False def IsCmdValid(self,txt): if txt==None: assert(0); return False return True
class hostList: def __init__(self, parent, id): assert(parent<>None) assert(id<>None) self.id=id self.ctrl=parent.FindWindowById(self.id) assert(self.ctrl<>None) #init list header self.config_column=[ #id; #name; #size; #after filling data we resize [0,"ID", wxLIST_AUTOSIZE_USEHEADER, wxLIST_AUTOSIZE], [1,"Job", wxLIST_AUTOSIZE_USEHEADER, wxLIST_AUTOSIZE], [2,"Work", wxLIST_AUTOSIZE_USEHEADER, wxLIST_AUTOSIZE], ] for c in self.config_column: self.ctrl.InsertColumn(c[0],c[1]) self.ctrl.SetColumnWidth(c[0], c[2]) def Refresh(self,workers): # filling data self.ctrl.DeleteAllItems() for i in range(0,5): index = self.ctrl.InsertStringItem(sys.maxint, "") #insert nothing, just get index self.ctrl.SetStringItem(index, 0, "val0") #0 means first column self.ctrl.SetStringItem(index, 1, "val1") self.ctrl.SetStringItem(index, 2, "val2") # after filling data, resize column for c in self.config_column: self.ctrl.SetColumnWidth(c[0], c[3]) class jobList: def __init__(self, parent, id, details=None): assert(parent<>None) assert(id<>None) self.id=id self.ctrl=parent.FindWindowById(self.id) assert(self.ctrl<>None) self.details=details #init list header self.config_column=[ #id; #name; #size; #after filling data we resize [0,"ID", wxLIST_AUTOSIZE_USEHEADER, wxLIST_AUTOSIZE], [1,"Owner", wxLIST_AUTOSIZE_USEHEADER, wxLIST_AUTOSIZE], [2,"Name", wxLIST_AUTOSIZE_USEHEADER, wxLIST_AUTOSIZE], [3,"Status", wxLIST_AUTOSIZE_USEHEADER, wxLIST_AUTOSIZE], [4,"Work", wxLIST_AUTOSIZE_USEHEADER, wxLIST_AUTOSIZE], ] for c in self.config_column: self.ctrl.InsertColumn(c[0],c[1]) self.ctrl.SetColumnWidth(c[0], c[2]) self.MessageMap(self.ctrl) def Refresh(self,jobs): # data buffer shared by other #print list_data #debug self.ctrl.DeleteAllItems() for i in range(0,5): index = self.ctrl.InsertStringItem(sys.maxint, "") #insert nothing, just get index self.ctrl.SetStringItem(index, 0, "val0") #0 means first column self.ctrl.SetStringItem(index, 1, "val1") self.ctrl.SetStringItem(index, 2, "val2") self.ctrl.SetStringItem(index, 3, "val3") # add better conversion to text self.ctrl.SetStringItem(index, 4, "val4") # after filling data, resize column for c in self.config_column: self.ctrl.SetColumnWidth(c[0], c[3])
#----- Message Map and Event Handler ----- begin def MessageMap(self,ctrl): EVT_LIST_ITEM_SELECTED(ctrl,self.id,self.OnItemSelected) EVT_LIST_ITEM_DESELECTED(ctrl,self.id,self.OnItemDeselected) def OnItemSelected(self,event): if self.details<>None: #dump everything about a job self.details.SetValue("rubbish data") pass pass def OnItemDeselected(self,event): print "OnListItemDeselected" #debug if self.details<>None: self.details.Clear() pass #----- Message Map and Event Handler ----- end
#main application class myApp(wxApp): def OnInit(self): #load ctrls from resources self.res = wxXmlResource("main.xrc") self.idf_main = self.res.LoadFrame(None, "idf_main") self.idc_main_menubar = self.res.LoadMenuBar("idc_main_menubar") self.idc_main_toolbar=self.res.LoadToolBar(self.idf_main,"idc_main_toolbar") self.idc_splitter_twobar=self.idf_main.FindWindowById(XRCID("idc_splitter_twobar")) self.idc_status_txt=self.idf_main.FindWindowById(XRCID("idc_status_txt")) self.idc_jobs_list1=jobList(self.idf_main,XRCID("idc_jobs_list1"),self.idc_status_txt) self.idc_jobs_list2=jobList(self.idf_main,XRCID("idc_jobs_list2"),self.idc_status_txt) self.idc_hosts_list1=hostList(self.idf_main,XRCID("idc_hosts_list1")) self.idc_hosts_list2=hostList(self.idf_main,XRCID("idc_hosts_list2")) self.idd_new=dlgNew(self.res.LoadDialog(self.idf_main,"idd_new")) # message map, self.MessageMap(self.idf_main) #binding ctrls self.idf_main.SetMenuBar(self.idc_main_menubar) self.idf_main.SetToolBar(self.idc_main_toolbar)
self.RefreshAll() #show time self.ShowMe() return True def RefreshAll(self): # get full master state self.RefreshAllJobList(None) self.RefreshAllHostList(None) # should alse display queue status somewhere (self.ms.state) def RefreshAllJobList(self,jobs): # jobList is a sequence of jobs (base class mgr.JobBase) self.idc_jobs_list1.Refresh(jobs) self.idc_jobs_list2.Refresh(jobs) def RefreshAllHostList(self, workers): # workers is dict of slave workers (base class mgr.Worker) self.idc_hosts_list1.Refresh(workers) self.idc_hosts_list2.Refresh(workers) def ShowMe(self): sizer = self.idf_main.GetSizer() sizer.Fit(self.idf_main) sizer.SetSizeHints(self.idf_main) self.idf_main.Show(True) self.SetTopWindow(self.idf_main)
def ShowMe(self): sizer = self.idf_main.GetSizer() sizer.Fit(self.idf_main) sizer.SetSizeHints(self.idf_main) self.idf_main.Show(True) self.SetTopWindow(self.idf_main) #----- Message Map and Event Handler ----- begin def MessageMap(self,ctrl): #menu EVT_MENU(ctrl, XRCID("idm_main_pause_queue"), self.OnPauseQ) EVT_MENU(ctrl, XRCID("idm_main_resume_queue"), self.OnResumeQ) EVT_MENU(ctrl, XRCID("idm_main_new"), self.OnNew) EVT_MENU(ctrl, XRCID("idm_main_exit"), self.OnBye) EVT_MENU(ctrl, XRCID("idm_main_options"), self.OnOptions) EVT_MENU(ctrl, XRCID("idm_main_index"), self.OnIndex) EVT_MENU(ctrl, XRCID("idm_main_refresh"), self.OnRefresh) EVT_MENU(ctrl, XRCID("idm_main_vertical"), self.OnVertical) EVT_MENU(ctrl, XRCID("idm_main_about"), self.OnAbout) #toolbar EVT_MENU(ctrl,XRCID("idc_toolbar_new"), self.OnNew) #google "wxToolBar" def OnPauseQ(self,event): pass def OnResumeQ(self,event): pass def OnNew(self,event): self.idd_new.ctrl.ShowModal() self.RefreshAll() def OnAbout(self,event): dlg = wxMessageDialog(self.idf_main, "None\n" "Version 1.0\n" "Copyright(C) 2005-2010 Redguardtoo", "About Me", wxOK | wxICON_INFORMATION) dlg.ShowModal() dlg.Destroy()
def OnBye(self,event): print "hello, I am OnBye" self.idf_main.Close(True) def OnOptions(self,event): print "hello, I am OnOptions" def OnIndex(self,event): print "hello, I am OnIndex" def OnRefresh(self,event): self.RefreshAll() def OnVertical(self,event): if not self.idc_splitter_twobar.IsSplit(): return w1=self.idc_splitter_twobar.GetWindow1() assert(w1) w2=self.idc_splitter_twobar.GetWindow2() assert(w2) s=self.idc_splitter_twobar.GetSplitMode() #some error self.idc_splitter_twobar.Unsplit() #have to , see document w1.Show(True) # when unsplitting , one pane hide , now we show them w2.Show(True) if s==wxSPLIT_VERTICAL: self.idc_splitter_twobar.SplitHorizontally(w1,w2) elif s==wxSPLIT_HORIZONTAL: self.idc_splitter_twobar.SplitVertically(w1,w2) else: assert(0) #----- Message Map and Event Handler ----- end if __name__=="__main__": app = myApp(0) app.MainLoop() ------------------------main.py-----------------------end
------------------------main.xrc-----------------------begin <?xml version="1.0" encoding="ISO-8859-1"?> <resource version="2.3.0.1"> <object class="wxFrame" name="idf_main"> <centered>1</centered> <style>wxDEFAULT_FRAME_STYLE</style> <title>IDL Job Manager</title> <object class="wxBoxSizer"> <orient>wxHORIZONTAL</orient> <object class="sizeritem"> <object class="wxSplitterWindow" name="idc_main_splitter"> <object class="wxSplitterWindow" name="idc_splitter_twobar"> <orientation>vertical</orientation> <minsize>1</minsize> <style>wxSP_3D|wxSP_BORDER</style> <object class="wxNotebook" name="idc_twobar_leftbar"> <usenotebooksizer>1</usenotebooksizer> <object class="notebookpage"> <label>Jobs</label> <object class="wxPanel" name="idc_leftbar_jobs"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxListCtrl" name="idc_jobs_list1"> <style>wxLC_REPORT</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> <selected>1</selected> </object> <object class="notebookpage"> <label>Hosts</label> <object class="wxPanel" name="idc_leftbar_hosts"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxListCtrl" name="idc_hosts_list1"> <style>wxLC_REPORT</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> </object> </object> <object class="wxNotebook" name="idc_twobar_rightbar"> <usenotebooksizer>1</usenotebooksizer> <object class="notebookpage"> <label>Jobs</label> <object class="wxPanel" name="idc_rightbar_jobs"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxListCtrl" name="idc_jobs_list2"> <style>wxLC_REPORT</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> <selected>1</selected> </object> <object class="notebookpage"> <label>Hosts</label> <object class="wxPanel" name="idc_rightbar_hosts"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxListCtrl" name="idc_hosts_list2"> <style>wxLC_REPORT</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> </object> </object> </object> <object class="wxNotebook" name="idc_main_status"> <usenotebooksizer>1</usenotebooksizer> <object class="notebookpage"> <label>Details</label> <object class="wxPanel" name="idc_status_details"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxTextCtrl" name="idc_status_txt"> <style>wxTE_MULTILINE|wxTE_READONLY</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> <selected>1</selected> </object> <object class="notebookpage"> <label>Output</label> <object class="wxPanel" name="idc_status_output"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxTextCtrl" name="idc_output_txt"> <style>wxTE_MULTILINE|wxTE_READONLY</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> </object> <object class="notebookpage"> <label>Errors</label> <object class="wxPanel" name="idc_status_errors"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxTextCtrl" name="idc_errors_txt"> <style>wxTE_MULTILINE|wxTE_READONLY</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> </object> <style>wxNB_BOTTOM</style> <object class="notebookpage"> <label>Master</label> <object class="wxPanel" name="idc_status_master"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxTextCtrl" name="idc_master_txt"> <style>wxTE_MULTILINE|wxTE_READONLY</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> </object> </object> <orientation>horizontal</orientation> <size>400,300</size> <style>wxSP_3D|wxSP_BORDER</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> <object class="wxMenuBar" name="idc_main_menubar"> <object class="wxMenu" name="idm_main_file"> <label>_File</label> <object class="wxMenuItem" name="idm_main_new"> <label>_New</label> </object> <object class="separator"/> <object class="wxMenuItem" name="idm_main_exit"> <label>E_xit</label> </object> </object> <object class="wxMenu" name="idm_main_admin"> <label>_Admin</label> <object class="wxMenuItem" name="idm_main_run_queue"> <label>_Run Queue</label> </object> <object class="wxMenuItem" name="idm_main_pause_queue"> <label>_Pause Queue</label> </object> <object class="wxMenuItem" name="idm_main_resume_queue"> <label>Resu_me Queue</label> </object> <object class="separator"/> <object class="wxMenuItem" name="idm_main_options"> <label>_Options</label> </object> <object class="separator"/> <object class="wxMenuItem" name="idm_main_login"> <label>_Login...</label> </object> <object class="wxMenuItem" name="idm_main_logout"> <label>Lo_gout</label> </object> </object> <object class="wxMenu" name="idm_main_job"> <label>_Job</label> <object class="wxMenuItem" name="idm_main_submit_job"> <label>_Submit Job</label> </object> <object class="wxMenuItem" name="idm_main_suspend_job"> <label>Sus_pend Job</label> </object> <object class="wxMenuItem" name="idm_main_resume_job"> <label>Resu_me Job</label> </object> <object class="wxMenuItem" name="idm_main_cancel_job"> <label>_CancelJob</label> </object> </object> <object class="wxMenu" name="idm_main_show"> <label>Sho_w</label> <object class="wxMenuItem" name="idm_main_refresh"> <label>_Refresh</label> </object> <object class="separator"/> <object class="wxMenuItem" name="idm_main_vertical"> <label>_Vertical Arrangement</label> </object> </object> <object class="wxMenu" name="idm_main_help"> <label>_Help</label> <object class="wxMenuItem" name="idm_main_index"> <label>_Index</label> </object> <object class="separator"/> <object class="wxMenuItem" name="idm_main_about"> <label>_About ...</label> </object> </object> <style>wxMB_DOCKABLE</style> </object> <object class="wxToolBar" name="idc_main_toolbar"> <style>wxTB_DOCKABLE|wxTB_DOCKABLE|wxTB_3DBUTTONS|wxTB_HORIZONTAL</style> <object class="tool" name="idc_toolbar_new"> <label>&New</label> <tooltip>New Job</tooltip> <longhelp>New Job</longhelp> <bitmap stock_id="wxART_FILE_OPEN"></bitmap> <bitmap2 stock_id="wxART_FILE_OPEN"></bitmap2> </object> </object> <object class="wxDialog" name="idd_new"> <title>New Job</title> <centered>1</centered> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxNotebook" name="idc_new_cat"> <usenotebooksizer>1</usenotebooksizer> <object class="notebookpage"> <label>Text Mode</label> <object class="wxPanel" name="idc_cat_textmode"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxTextCtrl" name="idc_textmode_txt"> <value>resize -v2 -i L:/images/Kyle/Nasa1 -i L:/images/Kyle/Violin w=512 h=389</value> <size>200,100</size> <style>wxTE_MULTILINE</style> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> </object> <selected>1</selected> </object> <object class="notebookpage"> <label>category1</label> <object class="wxPanel" name="idc_cat_category1"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxBoxSizer"> <orient>wxHORIZONTAL</orient> <object class="sizeritem"> <object class="wxStaticText"> <label>Option1:</label> </object> </object> <object class="sizeritem"> <object class="wxTextCtrl"> <value>value</value> </object> <border>0</border> </object> </object> </object> <object class="sizeritem"> <object class="wxBoxSizer"> <orient>wxHORIZONTAL</orient> <object class="sizeritem"> <object class="wxStaticText"> <label>Option1:</label> </object> </object> <object class="sizeritem"> <object class="wxTextCtrl"> <value>value</value> </object> </object> </object> </object> <object class="sizeritem"> <object class="wxBoxSizer"> <orient>wxHORIZONTAL</orient> <object class="sizeritem"> <object class="wxStaticText"> <label>Option1:</label> </object> </object> <object class="sizeritem"> <object class="wxTextCtrl"> <value>value</value> </object> </object> </object> </object> </object> </object> <selected>1</selected> </object> <object class="notebookpage"> <label>category2</label> <object class="wxPanel" name="idc_cat_category2"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> </object> </object> <selected>1</selected> </object> </object> <option>1</option> <flag>wxEXPAND</flag> </object> </object> <option>1</option> <flag>wxEXPAND</flag> </object> <object class="sizeritem"> <object class="wxStaticBoxSizer"> <label>General</label> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxGridSizer"> <cols>2</cols> <object class="sizeritem"> <object class="wxStaticText"> <label>Job Name:</label> </object> <flag>wxRIGHT</flag> <border>5</border> </object> <object class="sizeritem"> <object class="wxTextCtrl" name="idc_new_jobname"> <value>NEWJOB1</value> </object> <flag>wxALL|wxEXPAND</flag> <border>0</border> </object> <object class="sizeritem"> <object class="wxStaticText"> <label>Owner:</label> </object> <flag>wxRIGHT</flag> <border>5</border> </object> <object class="sizeritem"> <object class="wxTextCtrl" name="idc_new_owner"> <value>NEWOWNER1</value> </object> <flag>wxALL|wxEXPAND</flag> <border>0</border> </object> <vgap>2</vgap> </object> <flag>wxEXPAND</flag> </object> <object class="sizeritem"> <object class="wxCheckBox" name="idc_new_runnow"> <label>Submit Job &Immediately</label> <checked>1</checked> </object> <flag>wxEXPAND</flag> <border>5</border> </object> </object> </object> </object> <flag>wxEXPAND</flag> </object> <object class="sizeritem"> <object class="wxStaticLine"/> <flag>wxEXPAND</flag> </object> <object class="sizeritem"> <object class="wxBoxSizer"> <orient>wxHORIZONTAL</orient> <object class="sizeritem"> <object class="wxButton" name="idc_new_ok"> <label>&OK</label> <default>1</default> </object> <flag>wxRIGHT</flag> <border>10</border> </object> <object class="sizeritem"> <object class="wxButton" name="idc_new_cancel"> <label>&Cancel</label> </object> <flag>wxRIGHT</flag> <border>10</border> </object> <object class="sizeritem"> <object class="wxButton" name="idc_new_apply"> <label>&Apply</label> </object> <flag>wxRIGHT</flag> <border>10</border> </object> </object> <flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag> <border>10</border> </object> </object> <style>wxDEFAULT_DIALOG_STYLE</style> </object> </resource> ------------------------main.xrc-----------------------end
|