|
本文介绍代码统计工具的窗口界面,使用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()
|