基于Python和wxPython的代码格式化工具V1.0
Jan 8, 2014
本文代码基于 python 2.x 版本
近期在看Python,感叹Python的字符串处理功能之强大,突然想自己写一个格式化代码的脚本练练手,开始构想的功能很简单,读取未格式化的代码,然后将其缩进(类似于Visual Studio中的代码格式化)。主要是处理大括号{、}的问题。昨天写了一段脚本,实现了这个功能。想到自己反正要学Python的GUI编程,索性就安装了wxPython,因为有好几年的MFC开发基础,所以UI框架写得也很快,今天就完成了。于是就有了本文的这个小程序-代码格式化工具V1.0。利用这篇博客详细讲一下程序开发思路和源码。
功能 #
目前完成的功能还是很简单,核心就是代码的格式化,辅助有文件的打开、保存。
- 格式化:将左侧文本框中的代码格式化,并显示到右侧文本框中
- 新建:新建一个空白文档,可以直接在左侧文本框中输入代码
- 打开:打开一个已有的代码文本
- 保存:源文件修改后可以再保存,格式化的结果也可以另存到文件 格式化功能目前只是简单的处理了冗余的空格,然后依据大括号{、}进行缩进。 后续可以再强化一下格式化功能,有时间再把代码高亮功能扩展上去。
程序思路 #
程序主要分为两个模块:FormatFile.py 和 FormatFileUI.py。前者负责代码的格式化,后者负责创建和维护整个UI框架。
FormatFile.py 删除代码中的冗余,利用{}进行缩进。主要涉及的知识点有文件读取、字符编码转换、正则表达式(用于查找处理’{‘和’}’)
FormatFileUI.py模块基于wxPython,新建了一个GUI框架,并添加了菜单、工具栏、状态栏、两个文本框,设定了事件响应。导入FormatFile.py模块,处理格式化。
FormatFile.py模块 #
FormatFile.py模块对外提供三个函数:
readFile2String(filename)
,读入文件filename到unicode 字符串中并返回formatString(ustr,tab_size=4)
,对unicode字符串ustr进行格式化并返回格式化后的unicode字符串,tab_size指示每层缩进的空格数formatFile(filename,tab_size=4)
,对文件filename进行格式化并返回格式化后的unicode字符串(上面两个函数的综合)
格式化流程为:首先使用readFile2String()读入代码文件,然后利用__stripFile()删除代码中每行的冗余空格,再使用__handleBraces()将每个 { 和 } 单独成一行,最后使用__reindent()将文件根据大括号的层次在每行前面加上相应数量的空格。
FormatFile.py 模块代码 #
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#author:JarvisChu
#blog:zhujiangtao.com
#读入文件到string中,并返回
def readFile2String(filename):
#filename = u'src.c'
f = file(filename)
src = f.read()
f.close()
usrc = unicode(src,'gbk') #转换成unicode
return usrc
#1. 去除每一行开头末尾多余空格
def __stripFile(ustr): #__为了将函数私有
'''去除文本中每一行开头末尾多余空格
ustr为要处理的unicode文本'''
striped = [line.strip() for line in ustr.splitlines()]
ustr = u'\n'.join(striped)
return ustr
#2. 处理文本中的大括号{、}
def __handleBraces(ustr):
'''处理unicode文本ustr中的大括号{、}。
大括号单独成行,且前后没有多余的空行'''
#首先将{、} 前后都强制加上换行
#print u'处理{、},前后都换行'
import re
ustr = re.sub(r'[{]',u'\n{\n',ustr) #将{替换成\n{\n
ustr = re.sub(r'[}]',u'\n}\n',ustr) #将}替换成\n}\n
#print ustr
#然后去除{、}前后的多余行
ustr = re.sub(r'\n\n+[{]',u'\n{',ustr) #去除{前多余的行
ustr = re.sub(r'[{]\n\n+',u'{\n',ustr) #去除{前多余的行
ustr = re.sub(r'\n\n+[}]',u'\n}',ustr) #去除}前多余的行
ustr = re.sub(r'[}]\n\n+',u'}\n',ustr) #去除}前多余的行
#print ustr
return ustr
#在一行字符串s开头加上spaceCount个空格
def __reindent_line(s,spaceCount):
head = spaceCount * ' '
return head+s
#3. 处理缩进
def __reindent(ustr,tab_size=4):
'''将unicode文本ustr进行缩进'''
level = 0#缩进等级,即一行开头要缩进的次数
#tab_size = 4 #一次缩进的空格数
pieces = []
for line in ustr.splitlines():#逐行处理
#经过上面的处理,每个{和}都独自成行了
if(line == u'{'):
line = __reindent_line(line,level*tab_size)
level += 1
elif(line == u'}'):
level -= 1
line = __reindent_line(line,level*tab_size)
else:
line = __reindent_line(line,level*tab_size)
pieces.append(line)
ustr = u'\n'.join(pieces)
#print ustr
return ustr
#格式化文本
def formatString(ustr,tab_size=4):
ustr = __stripFile(ustr)
ustr = __handleBraces(ustr)
ustr = __reindent(ustr,tab_size=tab_size)
return ustr
#格式化文件
def formatFile(filename,tab_size=4):
ustr = readFile2String(filename)
ustr = formatString(ustr,tab_size=tab_size)
return ustr
if __name__ == '__main__':
filename = raw_input("File to Format:")
#filename = u"src.c"
print formatFile(filename)
FormatFile.py 代码详解 #
readFile2String(filename)
函数,打开文件filename文件,将其内容读取到src字符串中,为了支持中文的显示和处理,再利用unicode()函数将src转换为gbk的字符串。unicode(object[, encoding[, errors]),将object转换为指定的编码encodeing,encoding可以是’gbk’,‘utf-8’,‘uft-16’等等
__stripFile(ustr)
函数,去除文本中每一行开头末尾多余空格。函数名前面加”__”的函数为私有函数,只在本模块中可见。ustr.splitlines()将文本划分成行(如果传入参数True,则每一行末尾包括一个\n,默认为False不包括\n),并对每一行文本执行strip()删除收尾冗余空白,这样所有行都左对齐了。striped = [line.strip() for line in ustr.splitlines()]是一个列表综合(列表推导)语法。最后使用’\n’将每一行连接起来形成一个字符串。
__handleBraces(ustr)
函数,首先将所有的’{’ 和 ‘}‘都前后都加入一行空行,方法是使用正则表达式的 re.sub(pattern, repl, string, count=0, flags=0) 函数。ustr = re.sub(r’[{]’,u’\n{\n’,ustr),利用模式 r’[{]’ 查找ustr中所有的 ‘{’,并且替换成 u’\n{\n’。经过结果上一步的插入空行,可能会出现冗余空行,需要再次使用re.sub去除。
__reindent_line(s,spaceCount)
函数,在一行字符串s开头加上spaceCount个空格。这里要注意spaceCount * ’ ‘的用法。这个函数主要是由下面的__reindent调用。
__reindent(ustr,tab_size=4)
函数,处理缩进。level表示要缩进的层次,初始为0,表示不用缩进,左对齐;每当遇到{,则level+1;每当遇到},则level-1。逐行处理文本ustr,根据内容设定level,并根据level在每一行前面加上相应数量的空格。
formatString(ustr,tab_size=4)
函数,实现unicode字符串ustr的格式化。方法就是调用了上述每一个处理函数。
formatFile(filename,tab_size=4)
函数,实现文件的格式化。方法就是readFile2String和formatString的。 最后利用__name__ == ‘main‘判断该模块是单独运行还是被其他模块调用。单独运行则提示用户输入一个文件名,执行格式化。
FormatFileUI.py模块 #
FormatFileUI模块具有典型的wxPython框架风格,wxPython与MFC与很多的相似之处,比如事件响应、基本控件使用等,有MFC基础后wxPython入门就不太难。
该模块首先从wx.App派生了FormatFileApp类作为程序App,在FormatFileApp的OnInit函数中新建了一个FormatFileFrame框架作为程序的主框架。使用app = FormatFileApp()新建一个App对象,然后调用app.MainLoop()执行消息循环即可实现GUI App。FormatFileFrame框架派生自wx.Frame类,并添加了菜单、工具栏、状态栏、两个文本框,设定菜单的消息响应执行相关逻辑功能。
通过导入FormatFile.py模块,实现具体的格式化功能。
FormatFileUI.py模块代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#author:JarvisChu
#blog:zhujiangtao.com
'''代码格式化'''
import wx
import os
import FormatFile
class FormatFileFrame(wx.Frame):
'''程序主框架'''
def __init__(self,parent=None,id=-1,title="Frame",pos=wx.DefaultPosition,size=(800,600),style=wx.DEFAULT_FRAME_STYLE,name='frame'):
#id相当于MFC中的ID
#title是标题,name是名字,name可用来寻找该Frame
wx.Frame.__init__(self,parent=parent,id=id,title=title,pos=pos,size=size,style=style,name=name)
#设置窗口的图标
self.icon = wx.Icon('main.ico', wx.BITMAP_TYPE_ICO)
self.SetIcon(self.icon)
#窗口居中
self.Centre()
#变量
self.title = title #窗体标题栏显示的名字
self.tab_size = 4 #每层缩进的空格数
self.filename = u''#当前打开的文件名
#软件支持的格式,用于打开和保存文件对话框中
self.wildcard = "C files(*.c)|*.c|" \
"C++ files(*.cpp)|(*.cpp)|" \
"C# files(*.cs)|(*.cs)|" \
"Text files(*.txt)|(*.txt)|" \
"All files(*.*)|*.*"
#菜单和控件的ID
self.IDM_NEW_FILE = wx.NewId()
self.IDM_OPEN_FILE = wx.NewId()
self.IDM_EXIT = wx.NewId()
self.IDM_FORMAT = wx.NewId()
self.IDM_FORMAT_OPTION = wx.NewId()
self.IDM_SAVE_SRC = wx.NewId()
self.IDM_SAVE_TAG = wx.NewId()
self.IDM_ABOUT = wx.NewId()
#创建菜单
menuBar = wx.MenuBar() #菜单栏
menu1 = wx.Menu() #创建菜单1
menu1.Append(self.IDM_NEW_FILE,u"新建(&N)",u"新建空白文件")#菜单项
menu1.Append(self.IDM_OPEN_FILE,u"打开(&O)",u"打开文件")
menu1.AppendSeparator() #分隔符
menu1.Append(self.IDM_SAVE_SRC,u"保存源文件(&S)",u"保存左侧文本框内容到源文件")
menu1.Append(self.IDM_SAVE_TAG,u"保存格式化文件(&T)",u"将右侧文本框中格式化后的文本保存到文件")
menu1.AppendSeparator() #分隔符
menu1.Append(self.IDM_EXIT,u"退出(&E)",u"退出程序")
menuBar.Append(menu1,u"文件(&F)")
menu2 = wx.Menu() #创建菜单2
menu2.Append(self.IDM_FORMAT,u"格式化(&F)",u"将左侧源文件文本框中的内容格式化,并存储到右侧文本框中")
menu2.Append(self.IDM_FORMAT_OPTION,u"格式化选项(&O)",u"格式化选项")
menuBar.Append(menu2,u"编辑(&E)")
menu3 = wx.Menu() #创建菜单3
menu3.Append(self.IDM_ABOUT,u"关于软件(&H)",u"代码格式化工具(V1.0),作者:JarvisChu,博客:zhujiangtao.com")
menuBar.Append(menu3,u"关于(&A)")
self.SetMenuBar(menuBar) #附加菜单栏到窗体
#创建状态栏
statusBar = self.CreateStatusBar()
#创建快捷工具栏
toolBar = self.CreateToolBar()
toolBar.AddSimpleTool(self.IDM_NEW_FILE,wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_TOOLBAR),u"新建",u"新建空白文件")
toolBar.AddSimpleTool(self.IDM_OPEN_FILE,wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR),u"打开",u"打开文件")
toolBar.AddSimpleTool(self.IDM_FORMAT,wx.ArtProvider.GetBitmap(wx.ART_EXECUTABLE_FILE, wx.ART_TOOLBAR),u"格式化",u"将左侧源文件文本框中的内容格式化,并存储到右侧文本框中")
toolBar.AddSimpleTool(self.IDM_SAVE_SRC,wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR),u"保存源文件",u"保存左侧文本框内容到源文件")
toolBar.AddSimpleTool(self.IDM_SAVE_TAG,wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE_AS, wx.ART_TOOLBAR),u"保存格式化后的文件",u"将右侧文本框中格式化后的文本保存到文件")
toolBar.AddSimpleTool(self.IDM_ABOUT,wx.ArtProvider.GetBitmap(wx.ART_TIP, wx.ART_TOOLBAR),u"关于",u"代码格式化工具(V1.0),作者:JarvisChu,博客:zhujiangtao.com")
toolBar.Realize()
#创建面板
panel = wx.Panel(self, -1)
#创建左侧显示源文件内容的文本框
self.srcRichTxt = wx.TextCtrl(panel,style=wx.TE_MULTILINE | wx.TE_RICH2)
self.srcRichTxt.SetInsertionPoint(0)
#创建右侧显示格式化后文件内容的文本框
self.tagRichTxt = wx.TextCtrl(panel, style=wx.TE_MULTILINE | wx.TE_RICH2)
self.tagRichTxt.SetInsertionPoint(0)
#布局
sizer = wx.GridSizer(rows=1, cols=2, hgap=10, vgap=0)
sizer.AddMany([(self.srcRichTxt,0, wx.EXPAND), (self.tagRichTxt,0, wx.EXPAND)])
panel.SetSizer(sizer)
#事件响应
self.Bind(wx.EVT_MENU,self.OnNewFile,id=self.IDM_NEW_FILE)
self.Bind(wx.EVT_MENU,self.OnOpenFile,id=self.IDM_OPEN_FILE)
self.Bind(wx.EVT_MENU,self.OnSaveSrcFile,id=self.IDM_SAVE_SRC)
self.Bind(wx.EVT_MENU,self.OnSaveTagFile,id=self.IDM_SAVE_TAG)
self.Bind(wx.EVT_MENU,self.OnExit,id=self.IDM_EXIT)
self.Bind(wx.EVT_MENU,self.OnFormatFile,id=self.IDM_FORMAT)
self.Bind(wx.EVT_MENU,self.OnFormatOption,id=self.IDM_FORMAT_OPTION)
self.Bind(wx.EVT_MENU,self.OnAbout,id=self.IDM_ABOUT)
#初始化时新建一个空白文件
self.CreateNewFile()
def CreateNewFile(self):
'''创建空白文档'''
self.filename = u"未命名文件"
self.SetTitle(self.title + ' – ' + self.filename)
self.srcRichTxt.Clear()
self.tagRichTxt.Clear()
def SetWindowTitle(self,title):
'''设置窗体的名字'''
self.SetTitle(title)
def OnNewFile(self,event):
'''新建空白文件'''
self.CreateNewFile()
def OnOpenFile(self,event):
'''打开文件'''
#打开文件对话框
dlg = wx.FileDialog(self, u"打开文件",
os.getcwd(),
style = wx.OPEN,
wildcard = self.wildcard)
if dlg.ShowModal() == wx.ID_OK:
self.filename = dlg.GetPath()
self.srcRichTxt.Clear()
self.srcRichTxt.AppendText(FormatFile.readFile2String(self.filename))#读取文件内容到左侧文本框
self.SetTitle(self.title + ' – ' + self.filename)#设置窗体的标题为"软件名 – 文件名"
dlg.Destroy()
def OnSaveSrcFile(self,event):
'''直接将srcRichText文本框中的文本写入self.filename中'''
#s = u"中文abc"
#f1 = open(u'题目','w')
#f1.write(s.encode('gbk'))
#f1.close()
if self.srcRichTxt.GetValue() != u"" and self.filename != u"" and self.filename != u"未命名文件":
f = open(self.filename,'w')
f.write((self.srcRichTxt.GetValue()).encode('gbk'))
f.close()
elif self.filename == u"未命名文件":
#打开文件保存对话框
dlg = wx.FileDialog(self,
u"保存新建的源文件到文件…",
os.getcwd(),
style = wx.SAVE | wx.OVERWRITE_PROMPT,
wildcard = self.wildcard)
if dlg.ShowModal() == wx.ID_OK:
self.filename = dlg.GetPath()
print self.filename
if not os.path.splitext(self.filename)[1]: #如果用户没写后缀名
self.filename = self.filename + u'.txt'
print self.filename
f = open(self.filename,'w')
f.write((self.srcRichTxt.GetValue()).encode('gbk'))
f.close()
self.SetTitle(self.title+' – '+self.filename)
dlg.Destroy()
def OnSaveTagFile(self,event):
'''打开保存文件对话框,将tagRichText文本框中的文本写入文件'''
if self.tagRichTxt.GetValue() != u"" and self.filename != u"":
dlg = wx.FileDialog(self,
u"保存格式化文本到文件…",
os.getcwd(),
style = wx.SAVE | wx.OVERWRITE_PROMPT,
wildcard = self.wildcard)
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPath()
if not os.path.splitext(filename)[1]: #如果用户没写后缀名
filename = filename + u'.txt'
f = open(filename,'w')
f.write((self.tagRichTxt.GetValue()).encode('gbk'))
f.close()
dlg.Destroy()
def OnExit(self,event):
'''退出程序'''
self.Close(True)
def OnFormatFile(self,event):
'''将左侧源文件文本框中的内容格式化,并存储到右侧文本框中'''
ustr = self.srcRichTxt.GetValue()
self.tagRichTxt.Clear()
self.tagRichTxt.AppendText(FormatFile.formatString(ustr,self.tab_size))
def OnFormatOption(self,event):
'''格式化选项'''
option = wx.MessageDialog(None, u'默认每层缩进4个空格',u'提示', wx.OK)
option.ShowModal()
option.Destroy()
def OnAbout(self,event):
'''关于对话框'''
about = wx.MessageDialog(None, u'代码格式化工具(V1.0)\n作者:JarvisChu\n博客:zhujiangtao.com',u'关于', wx.OK)
about.ShowModal()
about.Destroy()
class FormatFileApp(wx.App):
'''主程序类'''
def OnInit(self):
id = wx.NewId()
self.frame = FormatFileFrame(parent=None,id=id,title=u'代码格式化工具(V1.0)')
self.frame.Show()
self.SetTopWindow(self.frame)
return True
if __name__ == "__main__":
app = FormatFileApp()
app.MainLoop()
FormatFileUi.py 代码详解 #
FormatFileApp类
继承自wx.App,代表了一个wxPython程序。OnInit函数会被自动调用。OnInit函数中创建了一个Frame,然后使用Show()函数显示窗体,默认参数为True,如果使用Show(False)则不会显示窗体。SetTopWindows()将frame设置为顶层窗体,这个在程序有很多Frame时有作用,只有一个Frame时可以不写。当程序很简单时,也可以不继承wx.App直接使用app = wx.PySimpleApp() 来获得一个程序App。推荐方式是继承wx.App。
FormatFileFrame类
继承自wx.Frame,是程序的主窗体。__init__()
函数为初始化函数,其中必须调用父类wx.Frame的__init__()
函数。
__init__(self,parent=None,id=-1,title="Frame",pos=wx.DefaultPosition,size=(800,600),\
style=wx.DEFAULT_FRAME_STYLE,name='frame')
- parent,父窗口,没有则为None;
- id,窗口的全局唯一ID标识(与MFC中的ID一样),-1表示系统随机生成一个;
- title,窗口标题,显示在标题栏;
- pos,窗口的显示位置,可以通过坐标指定,如pos=(10,10);
- size,窗口大小;
- style,窗口的样式,DEFAULT_FRAME_STYLE带有最大、最小、关闭按钮,可以使用 | 增加样式,使用 ^ 去除某个样式;
- name,窗口的名字,可以用来查找该窗口。
在__init__
函数中,创建了菜单、工具栏、状态栏以及窗口上的两个文本框,并设定了事件响应。
菜单
菜单分为三个层次,wx.MenuBar菜单栏,wxMenu菜单,菜单项。通过menuBar = wx.MenuBar() 创建一个菜单栏,通过menu1 = wx.Menu()创建一个菜单,使用menu1.Append()函数向菜单中添加菜单项,使用menuBar.Append()函数向菜单栏添加菜单。最后使用Frame类的SetMenuBar(menuBar)将菜单栏附加到窗口中。
状态栏
使用Frame类的CreateStatusBar()函数可以创建一个状态栏。菜单的提示信息,都会在状态栏显示。
statusBar = self.CreateStatusBar() #创建状态栏
工具栏
使用toolBar = self.CreateToolBar()创建一个工具栏,使用toolBar.AddSimpleTool()向工具栏中添加工具,最后使用toolBar.Realize()显示工具栏。
toolBar.AddSimpleTool(self.IDM_NEW_FILE, wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_TOOLBAR), u"新建",u"新建空白文件")
- 第一个参数为工具的ID,如果设置和某个菜单项的ID相同,则事件响应和菜单项相同,(与MFC中一样);
- 第二个参数为工具的图标,可是自己添加图像,也可以是库中的图像,使用wx.ArtProvider.GetBitmap()来获得库中的预定义的图像,如wx.ART_NEW为一个新建文本的图像,ART_FILE_OPEN为一个打开文件的图像,更多选择参见文档;
- 第三个参数为当鼠标停留时,显示在旁边的提示文本;第四个参数是当鼠标停留时,显示在状态栏的提示文本。
文本框
wx.TextCtrl文本框控件,通过指定其style为 wx.TE_MULTILINE | wx.TE_RICH2 实现多行显示和富文本显示。设置为富文本显示主要是为了后续代码着色做准备。
self.srcRichTxt = wx.TextCtrl(panel,style=wx.TE_MULTILINE | wx.TE_RICH2)
面板、布局
wx.Panel控件是一个容器,可以放置其他的控件。wxPython中面板和布局的概念与WPF、Java Swing中面板、布局概念大致相同。布局的作用在于使得窗口大小变化时,窗口上的控件也会随之相对变化。
sizer = wx.GridSizer(rows=1, cols=2, hgap=10, vgap=0)
sizer.AddMany([(self.srcRichTxt,0, wx.EXPAND), (self.tagRichTxt,0, wx.EXPAND)])
panel.SetSizer(sizer)
- 第一行代码创建了网格布局wx.GridSizer,一行两列,布局内的控件之间水平距离为10,垂直距离为0。
- 第二行代码向布局中添加了两个文本框控件。
- 第三行代码设定了panel的布局。
事件响应
wxPython中的事件响应和MFC中的消息响应机制几乎一样参阅最小化程序到托盘区。一个事件源(产生事件的控件)、一个事件类型(菜单点击、按钮按下、鼠标点击等)、一个事件响应函数(如OnBtnClick),最后通过一个绑定函数将三者绑定到一起。
self.Bind(wx.EVT_MENU,self.OnNewFile,id=self.IDM_NEW_FILE)
这是一个菜单消息的响应绑定。第一个参数为事件类型,第二个参数为事件响应函数,第三个参数为事件源的id。
文件对话框
wx.FileDialog是模块中提供的文件对话框。通过设定style=wx.OPEN或style=wx.SAVE来指定文件对话框是文件打开对话框还是文件保存对话框。
dlg = wx.FileDialog(self, u"打开文件",os.getcwd(),style = wx.OPEN,wildcard = self.wildcard)
if dlg.ShowModal() == wx.ID_OK:
self.filename = dlg.GetPath()
dlg.Destroy()
wildcard为文件类型筛选,其写法和MFC也相同。
#软件支持的格式,用于打开和保存文件对话框中
self.wildcard = "C files(*.c)|*.c|" \
"C++ files(*.cpp)|(*.cpp)|" \
"C# files(*.cs)|(*.cs)|" \
"Text files(*.txt)|(*.txt)|" \
"All files(*.*)|*.*"
Unicode文件的读写
本程序中使用的字符集是Unicode,保存和打开文件都需要使用Unicode字符集。读写Unicode文件时,使用open()函数。示例如下:
s = u"猪之草房子"
f = open(u'blog.txt','w')
f.write(s.encode('gbk'))
f.close()
设定程序窗口的图标
创建一个wx.Icon对象,打开指定的icon图标,然后使用wx.Frame的SetIcon()函数设定即可。示例:在主窗体Frame的 __init__
函数中使用如下代码
#设置窗口的图标
self.icon = wx.Icon('main.ico', wx.BITMAP_TYPE_ICO)
self.SetIcon(self.icon)
Stop Here
目前的V1.0版本大致就是如此了。程序的源码文中已尽数贴出并做了讲解。(如果不想复制粘贴,可以留下邮箱,我将打包源码发给你)。 未来的版本一则加强格式化功能,二则添加代码语法高亮。期待早点实现吧。