歡迎繼續關注開源項目CnblogsFan, 如果你是首次看到這個項目, 點擊此處查看有關該項目的詳細介紹。
按照項目實現的一般流程, 在對項目完成詳細設計后的下一步就是進入編碼階段了。 由於目前依然是一個人在在每天得空閑時間負責這個小項目, 在編碼上, wid采用的是由易到難, 逐步深入的方式。 所以, 今天第一步要實現的就是在主界面的布局。
在繼續閱讀以下隨筆之前, 你應該具備的知識:
1>. Python的基本語法
2>. 能夠使用WxPython創建一個窗口
如果你還沒有接觸過Python語言並且想要了解它, 點擊這里;
我們知道, 在WxPython中, 可以使用尺寸器sizer對窗口控件進行智能布局, 這是在WxPython中實現對窗口控件布局管理的常用方法, 但是wid最近在學習C語言Windows程序設計, 不知在這里有沒有能夠對窗口控件實現智能布局的API, 經過一番考慮后, 所以在這個小項目中, 決定不使用sizer對窗口進行智能布局, 而是根據取得上一個控件的RECT結構對下一個控件進行布局, 對於這種布局管理, 首先有個弊端, 在進行調整窗口大小時, 窗口中的控件位置以及大小不能根據窗口的大小而變化, 如果要實現像sizer尺寸器中那樣能夠根據窗口的大小自動調整控件位置以及大小的話, 可以根據一個wx.SIZE消息來調整控件的大小以及相對坐標。為了避免將這個弊端體現出來, 所以在窗口的樣式上調整為不可調整大小的窗口。
聲明: CnblogsFan中所使用的所有圖標文件均來自互聯網, 並遵循相關的使用協議, 關於圖標的來源記錄以及使用協議如下, 如果您也要使用以下圖標請認真閱讀:
圖標來源記錄及使用協議
======================
*該項目中使用的所有圖標資源均來自互聯網, 通過圖標搜索引擎**http://www.easyicon.cn**獲取, 圖標有關記錄如下:
******
*文件名: CnblogsFan_Spider.png
>尺寸: 48x48
>作者: Alessandro Rei
>作者網站: http://www.kde-look.org/usermanager/search.php?username=mentalrey
>使用協議: GPL
******
*文件名: CnblogsFan_Single.png
>尺寸: 48x48
>作者: Oliver Scholtz (and others)
>作者網站: http://linux.softpedia.com/developer/Oliver-Scholtz-93.html
>使用協議: GPL
******
*文件名: CnblogsFan_Classify.png
>尺寸: 48x48
>作者: codefisher
>作者網站: http://codefisher.org
>使用協議: Creative Commons (Attribution-Noncommercial-Share Alike 3.0 Unported)
******
*文件名: CnblogsFan_Setting.png
>尺寸: 48x48
>作者: Pavel InFeRnODeMoN
>作者網站: http://www.kde-look.org/usermanager/search.php?username=InFeRnODeMoN
>使用協議: GPL
******
*文件名: ICON_CnblogsFan.ico
>尺寸: 48x48
>作者: Kyo Tux
>作者網站: http://kyo-tux.deviantart.com
>使用協議: Creative Commons (Attribution-Noncommercial-Share Alike 3.0 Unported)
在對UI設計部分進行介紹之前, 為了能夠對設計中提到的各個控件的位置有個大致的把握, 首先預覽下該代碼在Windows XP下與Linux (Ubuntu)下運行的實際效果圖:
一、在Windows XP下運行:

二、在Linux (Ubuntu)下運行

接下來開始開始對項目的UI設計部分進行介紹, 采用貼出完整代碼的形式, 說明均在注釋中。
#!/usr/bin/python #coding:utf-8 #------------------------------------------------------------------------------- # Name: CnblogsFan_MainFrame.py # Purpose: # # Author: Mr.Wid # # Created: 13-10-2012 # Copyright: (c) Mr.Wid 2012 # Licence: GNU GPL #------------------------------------------------------------------------------- import wx class MainFrame(wx.Frame): #從wx.Frame類得到繼承 def __init__(self): #初始化窗口 wx.Frame.__init__( self, parent = None, #無父窗口 title = u'CnblogsFan', #窗口標題:'CnblogsFan', size = ( ( 900, 600 ) ), #窗口大小900x600 style = wx.SYSTEM_MENU|wx.CAPTION|wx.MINIMIZE_BOX|wx.CLOSE_BOX #帶有最小化與最大化按鈕的窗口樣式 ) self.Center() #令窗口在屏幕中居中顯示 #-----加載程序圖標----- self.AppLogo = wx.Icon('src//ICON_CnblogsFan.ico', wx.BITMAP_TYPE_ICO) self.SetIcon(self.AppLogo) #-----創建窗口面板----- self.panel = wx.Panel(self) #-----創建狀態欄----- self.userStatus = self.CreateStatusBar() self.userStatus.SetFieldsCount(4) #將狀態欄分為4部分 self.userStatus.SetStatusWidths( [-1, -1, -1, -1] ) #划分比例為4等分 #-- #狀態欄上待顯示的文字 statusLabel = [ u' 當前狀態:', u' 采集速度:', u' 采集統計:', u' 任務統計:', ] #將文字標簽顯示在狀態欄上 for i in range( len(statusLabel) ): self.userStatus.SetStatusText( statusLabel[i], i ) #-----創建菜單欄外框StaticBox----- #這個StaticBox控件為首個控件 self.groupMenuBox = wx.StaticBox( self.panel, label = u'菜單', pos = (15, 10), #在首個控件處使用絕對坐標 size = (80, 400), #框大小為80x400 ) #--以下為菜單圖標在本地的文件名 #資源文件在src文件夾下, 使用代碼示例時請將src資源文件夾與該.py文件放在同一目錄 self.localImgSrc = [ 'CnblogsFan_Spider.png', 'CnblogsFan_Single.png', 'CnblogsFan_Classify.png', 'CnblogsFan_Setting.png', 'CnblogsFan_About.png' ] self.lstMenu = [] #菜單列表, 用來記錄菜單按鈕控件 menuTip = [ u'采集整個Cnblogs上的隨筆.', #當鼠標放在按鈕上的相關提示文字 u'采集指定博客上的隨筆.', u'采集Cnblogs首頁分類上的隨筆.', u'設置軟件的相關參數.', u'關於CnblogsFan的一些信息.' ] #菜單按鈕下方的文字說明 menuLabel = [ u'蜘蛛模式', u'指定采集', u'分類采集', u'軟件設置', u'關於軟件' ] rect = self.groupMenuBox.Rect #獲取第一個控件self.groupMenuBox的RECT結構 #x, y用來決定菜單按鈕的位置 #x = 上個控件的x坐標 + (上個控件的x方向寬度 - 一個按鈕的寬度) / 2, 這樣按鈕控件就能夠在groupMenuBox框中居中顯示了 #y = 上個控件在y方向上的坐標的三倍 x, y = rect[0] + ( rect[2]-48 )/2, rect[1] * 3 for i in range( len(self.localImgSrc) ): #for 循環生成按鈕控件 tempImg = wx.Image( 'src//'+ self.localImgSrc[i], wx.BITMAP_TYPE_ANY ) #從本地加載圖標文件 w, h = tempImg.GetSize() #獲取加載到的圖標尺寸 img = tempImg.Scale( w*0.8, h*0.8 ) #將圖像縮放至80% self.lstMenu.append( #創建一個菜單按鈕並將其加入到菜單按鈕列表中 wx.BitmapButton( self.panel, bitmap = img.ConvertToBitmap(), #將縮放后的按鈕圖片轉換為位圖 pos = ( x, y ) ) ) #--為每個按鈕增加標簽 wx.StaticText( self.panel, label = menuLabel[i], pos = ( x, y + 50 ) #之所以令y再加50是為了能夠讓每個標簽顯示在按鈕的下方, 而不是上方, 50這個值是經過測量按鈕RECT結構的值得到 ) y += self.lstMenu[i].Rect[0] + 45 #--為每個按鈕增加按鈕提示信息 self.lstMenu[i].SetToolTipString(menuTip[i]) #在完成一個控件的創建之后下面的創建算法就同上面的了 #------創建當前采集用戶信息欄----- rect = self.groupMenuBox.Rect #獲取上一個控件RECT結構 self.groupBlogsUserInfoBox = wx.StaticBox( self.panel, label = u'當前所在博客博主信息', pos = ( rect[0] + rect[2]+ 20, rect[1] ), size = ( 500, 100 ) ) #--用戶信息標簽 adminInfoLabel = [ u'昵稱:', u'園齡:', u'粉絲:', u'關注:', u'隨筆:', u'文章:', u'評論:', u'地址:' ] self.lstAdminInfo = [] #當前采集用戶信息列表 rect = self.groupBlogsUserInfoBox.Rect #獲取self.groupBlogsUserInfoBox的RECT結構 x, y = rect[0] + 20, rect[1] + 30 for i in range(len(adminInfoLabel)): #生成標簽控件 self.lstAdminInfo.append( #將標簽控件增添到lstAdminInfo列表當中 wx.StaticText( self.panel, label = adminInfoLabel[i], pos = ( x, y ) ) ) x += 150 #每個用戶信息標簽直接間隔150個單位 if x > 450: #當放夠3個標簽后換行放置另外3個標簽 x = rect[0] + 20 y += 20 #-----創建任務控制欄----- #用來控制在任務進行中的暫停/停止動作 rect = self.groupBlogsUserInfoBox.Rect self.groupControlBox = wx.StaticBox( #創建靜態框StaticBox self.panel, label = u'任務控制', pos = ( rect[0] + rect[2]+ 20, rect[1] ), #位置在當前采集用戶的標簽的左側 size = ( 230, 100 ) ) #--控制按鈕 self.btnPauseContinue = wx.Button( #創建暫停按鈕, 當在任務過程中按下"暫停"后, 暫停標簽還要能夠變成"繼續" self.panel, label = u'暫停', size = ( 60, 60 ), #按鈕大小 pos = ( rect[0] + rect[2]+ 50, rect[1] + 25 ) #位置 ) self.btnPauseContinue.Disable() #在未進行任務前將按鈕設為不可用 rect = self.btnPauseContinue.Rect self.btnStop = wx.Button( #創建"停止"按鈕, 用來中途中斷任務的進行 self.panel, label = u'停止', size = ( 60, 60 ), pos = ( rect[0] + rect[2]+ 50, rect[1] ) ) self.btnStop.Disable() #按鈕不可用 #-----成功采集信息欄----- #用於輸出成功采集到的隨筆信息 rect = self.groupBlogsUserInfoBox.Rect self.groupSucceedBox = wx.StaticBox( #靜態框 self.panel, label = u'成功采集', pos = ( rect[0], rect[1] + rect[3] + 20 ), size = ( 750, 280 ) ) #--成功采集列表 rect = self.groupSucceedBox.Rect self.lstSucceedResults = wx.ListCtrl( #創建成功采集列表框 self.panel, pos = ( rect[0] + 10, rect[1] + 20 ), style = wx.LC_REPORT|wx.LC_HRULES|wx.LC_VRULES, size = ( rect[2] - 20, rect[3] - 30 ) ) w = self.lstSucceedResults.Rect[2] #獲取列表框x方向寬度 self.lstSucceedResults.InsertColumn( col = 0, heading = u'隨筆名稱', width = w * 0.3 ) #創建是三個縱列, 分割比例為3:5:1.5, 為了美觀留下0.5給豎直滾動條 self.lstSucceedResults.InsertColumn( col = 1, heading = u'來源地址', width = w * 0.5 ) self.lstSucceedResults.InsertColumn( col = 2, heading = u'發布時間', width = w * 0.15 ) #用來告知用戶當前正在進行的動作 #-----當前動作信息欄----- rect = self.groupSucceedBox.Rect self.groupActionBox = wx.StaticBox( self.panel, label = u'當前動作', pos = ( rect[0], rect[1] + rect[3] + 20 ), size = ( 750, 110 ) ) #--動作輸出文本框, 使用文本框進行當前動作輸出 rect = self.groupActionBox.Rect self.txtFeedback = wx.TextCtrl( self.panel, size = ( rect[2] - 20, rect[3] - 30 ), pos = ( rect[0] +10, rect[1] + 20 ), style = wx.TE_MULTILINE | wx.TE_READONLY #帶有豎直方向的滾動條並且將文本框設為只讀模式 ) #在菜單創建欄的下方還剩一個比較小的角落, 用來作為用戶反饋意見的位置 #-----意見反饋欄----- rect = self.groupMenuBox.Rect self.groupFeedbackBox = wx.StaticBox( self.panel, label = u'告訴作者', pos = ( rect[0], rect[1] + rect[3] + 20 ), size = ( rect[2], 110 ), ) #--創建意見輸入文本框 rect = self.groupFeedbackBox.Rect self.txtFeedback = wx.TextCtrl( self.panel, size = ( rect[2] - 10, rect[3] - 50 ), pos = ( rect[0] + 5, rect[1] + 20 ), style = wx.TE_MULTILINE ) #--創建提交按鈕 self.txtFeedback.SetMaxLength(1024) rect = self.txtFeedback.Rect self.btnFeedback = wx.Button( self.panel, label = u'提交', pos = ( rect[0], rect[1] + rect[3] + 5 ), size = (rect[2], 20) ) def test(): cnblogsFan = wx.PySimpleApp() mainFrame = MainFrame() mainFrame.Show() cnblogsFan.MainLoop() if __name__ == '__main__': test()
所有項目文件均在GitHub上, 項目地址: https://github.com/mrwid/CnblogsFan
--------------------
說明: 這里僅僅是實現了主界面的相關布局, 對於相關的采集參數設置對話框, 軟件設置對話框、關於軟件對話框等相關的窗口的創建過程下次就不再往首頁上推了, 創建的過程都是差不多, 只是將這里的從wx.Frame類中繼承改為從wx.Dialog類中得到繼承, 其他也就是往客戶區放相關的控件, 沒什么可敘述的。最新的項目進展歡迎關注wid的博客, 或者從GitHub上獲得最新的項目代碼。
wid, 2012.10.15
上一篇: 開源->一步步實現cnblogs博客采集工具->詳細設計
