一时闲极无聊,想把心仪已久的python好好学习学习.随手做个文本编辑器来磨练下自己的手艺.
定好目标要做个文本编辑器后,就可以开始coding了.一个极简的文本编辑器,只需要打开文本,编辑文本,保存,退出这么几个简单的功能(这里暂时不考虑编码,文件内容查找之类的问题).
简单直接粗暴有效的function
01 | #-*-coding:utf8 -*- |
02 | __version__ = 0.1 |
03 | __author__ = "Alycat" |
04 |
05 | import sys |
06 |
07 | class Note(): |
08 | ''' |
09 | This fname is file name with full path |
10 | ''' |
11 | def openFile( self ,fname = None ): |
12 | if fname is None : |
13 | return - 1 |
14 | self .fname = fname |
15 | file = open (fname, 'r+' ) |
16 | content = file .read() |
17 | file .close() |
18 | return content |
19 |
20 | def saveFile( self ,content = None ): |
21 | if content is None : |
22 | return - 1 |
23 | file = open ( self .fname, 'w' ) |
24 | file .write(content) |
25 | file .flush() |
26 | file .close() |
27 | return 0 |
28 |
29 | def exit( self ): |
30 | sys.exit( 0 ) |
这个文本编辑器最终形态必定不是运行在黑窗口下类似Vi和Emasc的存在,所以在以后会慢慢给她添上GUI.以上的code将会作为文本编辑这个应用的功能模块,所以修改文本内容将缓存在UI里.
习惯了java,下意识在function外围上了class,实际上需要这个class么? 从python的在线文档这里 (oschina居然可以直接看doc,点赞)可以看到,在import module时会做2件事,查询并初始化这个目标module然后在当前脚本定义该module的名字.
既然是功能模块,那么象open,save,exit这些功能能不能直接用而不需要初始化Note这个对象呢?这个问题暂时放在一边,这个编辑器到现在只有几个简单的功能连UI都还没有,接下来就开始做个界面.
在大多数情况下,开发一个本地应用最简单的做法就是界面绑定功能,先做出界面再配合界面完善功能.在Python里做界面有几种做法,官方的Lib中默认的GUI库是用Tcl/Tk,在这里有相关的介绍.其次用的比较广泛的是wxPython,PyQT等等. 为了配合我们编辑器简单粗暴的做法,我们就使用官方自带的GUI库来定制界面.对刚才的代码添加上简单的界面:
01 | #-*-coding:utf8 -*- |
02 | __version__ = 0.1 |
03 | __author__ = "Alycat" |
04 |
05 | import sys |
06 | from Tkinter import * |
07 |
08 | class Note(): |
09 | |
10 | def __init__( self ): |
11 | self .tk = Tk() |
12 | self .createUI() |
13 | self .tk.mainloop() |
14 |
15 |
16 | def createUI( self ): |
17 | #create menu |
18 | menubar = Menu( self .tk) |
19 | fmenu = Menu(menubar,tearoff = 0 ) |
20 | fmenu.add_command(label = 'Open' ) |
21 | fmenu.add_command(label = 'Save' ) |
22 | fmenu.add_command(label = 'Exit' ) |
23 | menubar.add_cascade(label = "File" , menu = fmenu) |
24 | self .tk.config(menu = menubar) |
25 | self .text = Text() |
26 | self .text.pack() |
27 |
28 | ''' |
29 | The fname is file name with full path |
30 | ''' |
31 | def openFile( self ,fname = None ): |
32 | if fname is None : |
33 | return - 1 |
34 | self .fname = fname |
35 | file = open (fname, 'r+' ) |
36 | content = file .read() |
37 | file .close() |
38 | return content |
39 |
40 | def saveFile( self ,content = None ): |
41 | if content is None : |
42 | return - 1 |
43 | file = open ( self .fname, 'w' ) |
44 | file .write(content) |
45 | file .flush() |
46 | file .close() |
47 | return 0 |
48 |
49 | def exit( self ): |
50 | sys.exit( 0 ) |
51 |
52 | if __name__ = = '__main__' : |
53 | Note() |
这是UI截图:
看着象点样子了吧,这里用到了Menu和Text这2个Widget,具体的介绍可以看官方文档.
接下来就是把UI和之前的功能衔接起来,这里需要有一个地方需要做些修改,在保存和打开文件时,需要用户去定位文件路径和文件名.废话少说,继续粗暴的路线:
01 | #-*-coding:utf8 -*- |
02 | __version__ = 0.1 |
03 | __author__ = "Alycat" |
04 |
05 | import sys,tkFileDialog,os |
06 | from Tkinter import * |
07 |
08 | class Note(): |
09 | |
10 | def __init__( self ): |
11 | self .tk = Tk() |
12 | self .createUI() |
13 | self .tk.mainloop() |
14 |
15 |
16 | def createUI( self ): |
17 | #create menu |
18 | menubar = Menu( self .tk) |
19 | fmenu = Menu(menubar,tearoff = 0 ) |
20 | fmenu.add_command(label = 'Open' ,command = self . open ) |
21 | fmenu.add_command(label = 'Save' ,command = self .save) |
22 | fmenu.add_command(label = 'Exit' ,command = exit) |
23 | menubar.add_cascade(label = "File" , menu = fmenu) |
24 | self .tk.config(menu = menubar) |
25 | self .text = Text() |
26 | self .text.pack() |
27 | |
28 | def save( self ): |
29 | txtContent = self .text.get( 1.0 ,END) |
30 | self .saveFile(content = txtContent) |
31 | |
32 |
33 | def open ( self ): |
34 | self .filename = tkFileDialog.askopenfilename(initialdir = os.getcwd()) |
35 | filecontent = self .openFile(fname = self .filename) |
36 | if filecontent is not - 1 : |
37 | self .text.delete( 1.0 ,END) |
38 | self .text.insert( 1.0 ,filecontent) |
39 |
40 | ''' |
41 | The fname is file name with full path |
42 | ''' |
43 | def openFile( self ,fname = None ): |
44 | if fname is None : |
45 | return - 1 |
46 | self .fname = fname |
47 | file = open (fname, 'r+' ) |
48 | content = file .read() |
49 | file .close() |
50 | return content |
51 |
52 | def saveFile( self ,content = None ): |
53 | if content is None : |
54 | return - 1 |
55 | file = open ( self .fname, 'w' ) |
56 | file .write(content) |
57 | file .flush() |
58 | file .close() |
59 | return 0 |
60 |
61 | def exit( self ): |
62 | sys.exit( 0 ) |
63 |
64 | if __name__ = = '__main__' : |
65 | Note() |
到这里,一个极其简陋的文本编辑器已经完成,但是这不是最终形态,之后将陆续对这个简单粗暴的文本编辑器进行改造优化.