|
本文介绍代码统计工具的窗口界面,使用wxPython库实现了简易界面,见下图:
用wxPython编写界面,可以分为以下四步: 第一步:搭好框架,定义wx.App类和wx.Frame类的子类。 第二步:创建控件。 第三步:绑定消息。 第四步:编写响应消息的函数。 界面编写只懂些皮毛,所以这个程序只是实现了功能,并没有什么出彩的地方。 下面是CodeCounterW.pyw文件中的代码:
# -*- coding: cp936 -*- ''' 这是一个用Python写的简易代码统计工具。 作者:lemene 网址:http://www.cppblog/lemene ''' import wx import os from counter import CodeCounter
# 代码类型和对应的文件后缀名 codetyps = [['C','Python'], ['.c,.cpp,.h','.py']]
class ResultList(wx.ListCtrl): '''显示结果的控件''' def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.LC_REPORT): wx.ListCtrl.__init__(self, parent, ID, pos, size, style) self.InsertColumn(0, "文件名") self.InsertColumn(1, "总行数") self.InsertColumn(2, "代码") self.InsertColumn(3, "注释") self.InsertColumn(4, "空行")
def Clear(self): '''清空结果''' self.DeleteAllItems()
def ShowResult(self, results): '''显示结果''' i = 0 for res in results: self.InsertStringItem(i, res[0]) self.SetStringItem(i, 1, str(res[1][4])) self.SetStringItem(i, 2, str(res[1][1]+res[1][3])) self.SetStringItem(i, 3, str(res[1][2]+res[1][3])) self.SetStringItem(i, 4, str(res[1][0]) )
class CounterFrame(wx.Frame): '''程序界面''' def __init__(self, parent, title): wx.Frame.__init__(self, parent, -1, title, size=(495, 435), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
# 添加界面控件 panel = wx.Panel(self) # 第一行控件 text1 = wx.StaticText(panel, -1, "代码类型:",style=wx.ALIGN_RIGHT) cb1 = wx.ComboBox(panel, -1, codetyps[0][0],choices=codetyps[0],style=wx.CB_READONLY, size=(100,-1)) text2 = wx.StaticText(panel, -1, "后缀名:") cb2 = wx.ComboBox(panel, -1, codetyps[1][0],choices=codetyps[1],size=(190,-1)) sizer1 = wx.BoxSizer(wx.HORIZONTAL) sizer1.Add(text1, 0, wx.RIGHT|wx.LEFT, 10) sizer1.Add(cb1, 0, wx.RIGHT|wx.LEFT, 10) sizer1.Add(text2, 0, wx.RIGHT|wx.LEFT, 10) sizer1.Add(cb2, 0, wx.RIGHT|wx.LEFT, 10) # 第二行控件 rb = wx.RadioBox(panel, -1, "", wx.DefaultPosition, wx.DefaultSize, ['目录','文件']) ckb = wx.CheckBox(panel, -1, "包括子目录") fordtx = wx.TextCtrl(panel, -1, "", size=(190, -1)) openfdbtn = wx.Button(panel, -1, "", size=(25,25)) sizer2 = wx.BoxSizer(wx.HORIZONTAL) sizer2.Add(rb, 0, wx.RIGHT|wx.LEFT|wx.ALIGN_CENTER , 10) sizer2.Add(ckb, 0, wx.RIGHT|wx.LEFT|wx.ALIGN_CENTER , 10) sizer2.Add(fordtx, 0, wx.RIGHT|wx.LEFT|wx.ALIGN_CENTER , 10) sizer2.Add(openfdbtn, 0, wx.RIGHT|wx.LEFT|wx.ALIGN_CENTER , 10)
# 第三行控件 rzlist = ResultList(panel, -1, size=(470,250))
# 第四行控件 countbtn = wx.Button(panel, -1, "统计") savebtn = wx.Button(panel, -1, "保存") aboutbtn = wx.Button(panel, -1, "关于") sizer4 = wx.BoxSizer(wx.HORIZONTAL) sizer4.Add(countbtn, 0, wx.RIGHT|wx.LEFT, 40) sizer4.Add(savebtn, 0, wx.RIGHT|wx.LEFT, 40) sizer4.Add(aboutbtn, 0, wx.RIGHT|wx.LEFT, 40)
# 排列这四行控件 sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(sizer1, 0, wx.ALL, 8) sizer.Add(sizer2, 0, wx.ALL, 8) sizer.Add(rzlist, 0, wx.ALL, 8) sizer.Add(sizer4, 0, wx.ALL, 8) panel.SetSizer(sizer) panel.Layout()
# 控件消息 self.Bind(wx.EVT_BUTTON, self.OnOpenForD, openfdbtn) self.Bind(wx.EVT_BUTTON, self.OnCount, countbtn) self.Bind(wx.EVT_BUTTON, self.OnSave, savebtn) self.Bind(wx.EVT_BUTTON, self.OnAbout, aboutbtn) self.Bind(wx.EVT_COMBOBOX, self.OnChoiceCodeType, cb1) # 保存控件引用 self.codetype_cb = cb1 self.filetype_cb = cb2 self.fordname_tx = fordtx self.ford_rb = rb self.subdir_ckb = ckb self.result_list = rzlist
# 存放结果 self.result = []
def OnOpenForD(self, evn): '''得到需要统计的文件或目录的路径''' if self.ford_rb.GetSelection() == 0: dlg = wx.DirDialog(self, "选择目录:", style=wx.DD_DIR_MUST_EXIST ) else: dlg = wx.FileDialog( self, message="选择文件", defaultDir="", defaultFile="", style=wx.OPEN | wx.CHANGE_DIR ) if dlg.ShowModal() == wx.ID_OK: self.fordname_tx.SetValue(dlg.GetPath()) dlg.Destroy() def OnCount(self, evn): '''统计代码''' self.result_list.Clear() self.result = []
try: counter = CodeCounter(codefiles=[]) self.SetCounter(counter) counter.Count(self.result) except: self.ErrMsg("输入错误") all = [0,0,0,0,0] for ele in self.result: for i in range(len(ele[1])): all[i] += ele[1][i] self.result.append(['总计', all]) self.result_list.ShowResult(self.result)
def OnSave(self, evn): '''保存统计结果''' dlg = wx.FileDialog( self, message="Choose a file", defaultDir="", defaultFile="", wildcard="TXT files (*.txt)|*.txt|All files (*.*)|*.*", style=wx.SAVE ) if dlg.ShowModal() == wx.ID_OK: f = open(dlg.GetPath(), 'wt') for res in self.result: f.write(("%d\t%d\t%d\t%d\t%s\n" % (res[1][4],res[1][1]+res[1][3], res[1][2]+res[1][3], res[1][0], res[0]))) dlg.Destroy()
def OnChoiceCodeType(self, evn): idx = self.codetype_cb.GetSelection() self.filetype_cb.SetSelection(idx)
def OnAbout(self, evn): dlg = wx.MessageDialog(self, __doc__, 'About', wx.OK | wx.ICON_INFORMATION ) dlg.ShowModal() dlg.Destroy()
def ErrMsg(self,msg): dlg = wx.MessageDialog(self, msg, 'Err', wx.OK | wx.ICON_INFORMATION ) dlg.ShowModal() dlg.Destroy() def SetCounter(self, counter): '''从界面读入配置设置统计工具''' if self.subdir_ckb.IsChecked(): # 是否包含子目录 counter.SetLevel(-1)
if self.fordname_tx.GetValue() != '': # 判断是选择文件还是目录 t = 'f' if self.ford_rb.GetSelection() == 0: t = 'd' counter.AddCodeFiles(t, self.fordname_tx.GetValue())
# 设置要统计的代码类型 val = self.codetype_cb.GetValue() if val == 'C': counter.SetCodeType('c') elif val == 'Python': counter.SetCodeType('py') # 设置后缀名 counter.SetModes(self.filetype_cb.GetValue())
class CounterApp(wx.App): def OnInit(self): frame = CounterFrame(None, "代码计算器") self.SetTopWindow(frame) frame.Show(True) return True
if __name__ == '__main__': app = CounterApp(redirect=False) app.MainLoop()
|