欢迎继续关注开源项目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博客采集工具->详细设计