最近绞尽脑汁做了一个功能十分详细的文本编辑器,可能已经比得上microsoft的笔记本了,接下来我给你们介绍一下怎么做

本文章是作者自己的知识产权,可以让你们复制而且不付钱已经是很良心了,请多多点赞、收藏、阅读、评论,谢谢!

from tkinter import *
import windnd
from tkinter.messagebox import *
from tkinter.scrolledtext import *
from easygui import *
class gui():
    def __init__(self):
        self.win=Tk()
        self.win.geometry('892x685')
        self.win.title('文本编辑器')
        self.ss=False
        self.menu()
        self.text()
        self.tools()
    def menu(self):
        self.menubar=Menu(self.win,tearoff=0)
        self.file=Menu(self.menubar)
        self.file.add_command(label='新建',command=self.new,accelerator='ctrl+n')
        self.win.bind('<Control-N>',self.new)
        self.file.add_command(label='打开',command=self.op,accelerator='ctrl+o')
        self.win.bind('<Control-O>',self.op)
        self.file.add_command(label='保存',command=self.save,accelerator='ctrl+s')
        self.win.bind("<Control-S>",self.save)
        self.file.add_separator()
        self.file.add_command(label='清空',command=self.clear,accelerator='alt+c')
        self.win.bind("<Alt-C>",self.clear)
        self.file.add_separator()
        self.file.add_command(label='最小化',command=self.clo,accelerator='ctrl+q')
        self.win.bind('<Control-Q>',self.clo)
        self.file.add_command(label='关闭',command=self.ex,accelerator='alt+f4')
        self.win.bind("<Alt-F4>",self.ex)
        self.menubar.add_cascade(label='文件',menu=self.file)
        self.edit=Menu(self.menubar)
        self.edit.add_command(label='粘贴',command=self.pasts,accelerator='ctrl+v')
        self.win.bind("<Control-V>",self.pasts)
        self.edit.add_command(label='复制',command=self.copy,accelerator='ctrl+c')
        self.win.bind("<Control-C>",self.copy)
        self.edit.add_command(label='剪切',command=self.cut,accelerator='ctrl+x')
        self.win.bind("<Control-X>",self.cut)
        self.edit.add_separator()
        self.edit.add_command(label='撤销',command=self.undo,accelerator='ctrl+u')
        self.win.bind("<Control-U>",self.undo)
        self.edit.add_command(label='恢复',command=self.redo,accelerator='ctrl+r')
        self.win.bind("<Control-R>",self.redo)
        self.menubar.add_cascade(label='编辑',menu=self.edit)
        self.window=Menu(self.menubar)
        self.window.add_command(label='修改字体颜色',command=self.edd,accelerator='ctrl+f')
        self.win.bind("<Control-F>",self.edd)
        self.window.add_command(label='搜索',command=self.find,accelerator='alt+f')
        self.win.bind('<Alt-F>',self.find)
        self.menubar.add_cascade(label='窗口',menu=self.window)
        self.menubar.add_command(label='帮助',command=self.hlp)
        self.win.bind("<Control-H>",self.hlp)
        self.win['menu']=self.menubar
        windnd.hook_dropfiles(self.win,func=self.eve)
    def text(self):
        self.test=ScrolledText(self.win,width=96,height=29,undo=True)
        self.test.pack(expand=YES,fill=BOTH)
    def tools(self):
        self.frame=Frame(self.win,width=892,height=23)
        self.frame.pack(side=BOTTOM,fill=X)
        self.st=StringVar()
        self.st.set('第1行,第1列')
        self.l=Label(self.frame,textvariable=self.st)
        self.l.pack(side=LEFT,fill=X)
        self.win.bind("<Key>",self.pos)
        self.win.bind("<Button-1>",self.pos)
        self.win.bind("<Button-3>",self.me)
        self.win.protocol('WM_DELETE_WINDOW',self.bc)
    def new(self):
        if self.ss:
            a=buttonbox(msg='你是否要保存?',title='保存',choices=['是','否'])
            if a=='是':
                self.save()
            self.clear()
        self.ss=False
        self.win.title('untitle')
    def op(self):
        try:
            a=askopenfilename(defaultextension='.txt')
            b=open(a,'r',encoding='utf-8')
            c=b.read()
            self.test.delete(1.0,END)
            self.test.insert(END,c)
            b.close()
        except:
            showerror(title='错误',message='文本编辑器不能打开此文件!')
    def save(self):
        a=asksaveasfilename()
        fi=open(a,'w')
        fi.write(self.test.get(1.0,END).strip())
        fi.close()
        self.ss=True
        self.win.title('文本编辑器 '+str(a))
    def clear(self):
        self.test.delete(1.0,END)
    def clo(self):
        self.win.iconify()
    def ex(self):
        self.win.destroy()
    def pasts(self):
        self.test.event_generate("<<Paste>>")
    def copy(self):
        self.test.event_generate("<<Copy>>")
    def cut(self):
        self.test.event_generate("<<Cut>>")
    def undo(self):
        self.test.event_generate("<<Undo>>")
    def redo(self):
        self.test.event_generate("<<Redo>>")
    def eve(self,files):
        ss=files[0]
        bd=ss.decode('gbk')
        a=open(bd,'r')
        msg=a.read()
        self.test.insert(END,msg)
        self.win.title('文本编辑器 '+str(bd))
    def pos(self,event):
        po=str(self.test.index('insert')).split('.')
        msg='第'+str(po[0])+'行,第'+str(po[1])+'列'
        self.st.set(msg)
    def me(self,event):
        self.edit.post(event.x_root,event.y_root)
    def bc(self):
        a=buttonbox(msg='你要保存吗?',title='保存',choices=['是','否'])
        if a=='是':
            self.save()
            self.win.destroy()
        else:
            self.win.destroy()
    def edd(self):
        a=enterbox('请输入你要变化的颜色','字体颜色')
        try:
            tag=self.test.tag_add('tag1','1.0','end')
            self.test.tag_config('tag1',foreground=a)
        except:
            showerror('错误','没有此颜色')
    def find(self):
        a=enterbox('请输入你要搜索的内容','搜索')
        b=self.test.search(a, '1.0', stopindex=END)
        print(b)
        if not b:
            showerror('错误','没有此内容!')
        else:
            showinfo('查找成功','在第%s行第%s列'%(b.split('.')[0],str(int(b.split('.')[1])+1)))
    def hlp(self):
        a=Tk()
        b=Label(a,text='pythonitstream原创,不可转载!!')
        b.pack()

if __name__=='__main__':
    gui()
mainloop()

python开发一个文本编辑器 python制作文本编辑器_文本框

 

特长对不对?那好,我来分段解释

我这是python3.8.3,请不同版本的人不要误会

1)导入部分

可以看到前面我就用6行的篇幅导入了本程序需要的库,可见本程序不简单

tkinter:内置库,一个非常复杂的GUI库

tkinter.messagebox:内置库,属于一个tkinter下的库。导入tkinter时,会导入tkinter文件夹里的__init__文件(主文件),但还有几个文件没有被导入,哪个需要哪个导入。一个tkinter里的信息框库

tkinter.scrolledtext:内置库,原理同tkinter.messagebox。一个tkinter里的添加有滚动条的文本框的库

在此声明一下,我导入scrolledtext不是装B,由于Text和ttk.Scrollbar绑定太复杂,而且还需要导入另外一个库:tkinter.ttk,所以由于麻烦,我才导入的。请大家不要误解

easygui:外置库,需要自己下载。相当于tkinter.simpledialog的一个简单的GUI库

windnd:外置库,需要自己下载。用来检测Tk窗口的事件【普通事件可以用bind来检查,但是特殊事件(比如有文件拖入窗口)就得用windnd】

2)__init__部分

__init__初始函数我就不用介绍了吧?我相信大伙都知道

前三行创建窗口、设置大小、设置标题我就不用介绍了

值ss:正在打开的文件是否保存

方法menu:设置菜单并绑定关于菜单的事件

方法text:创建文本框

方法tools:绑定事件并添加工具栏

3)方法menu

方法menu好像是这个类里面最长的一个方法了……

首先我们回顾一下tkinter的菜单如何写

菜单基类.add_command(label=菜单文本,command=菜单被触发时的函数,accelerator=快捷键)

声明:accelerator快捷键只是标注一下,并没有绑定

所以我们还要绑定菜单的快捷键

基类.bind('<快捷键>',触发函数)

这是绑定事件的语法

鼠标也是这样绑定的

所以这个方法就是绑定菜单,绑定快捷键

最后一行我绑定了把文件拖拽到窗口内部时的事件,我们要把文件的路径获得,并打开文件、读取文件,之后把文件内容呈现到文本框里

4)方法text

这个好像不用我多说,这玩意只是创建一个文本框,undo=True是指可以撤销,默认为False

5)方法tools

这个方法用来添加文本框下面的工具栏(显示第几行,第几列),主要就是弄一个Frame,然后染色,然后在里面添加一个绑定过StringVar的Label,就是工具栏了!啦啦啦!

每当用户按下键盘或鼠标左键的时候,这时候意味着文本框中的光标的位置出现了变化,所以我们也要更新Label里面的内容啦!

Tk.protocol好像说起来有点复杂,它用来检测窗口的属性变化事件。WM_DELETE_WINDOW就是关闭窗口的事件,关闭窗口要询问用户保不保存

6)方法new

new就是新的的意思,在这里用于新建文档

首先判断用户是否保存,保存了才能新建

self.clear是清屏的函数,我自己后面写的

新建后,把self.ss调整为未保存,把标题调整为untitled,这和普通笔记本没啥区别

7)方法op

op在这里是一个简写,全写为open,但我怕和内置函数混了,所以用的缩写

askopenfilename是easygui库的一个函数,用来返回用户所选的路径

之后就是打开文件,读取文件,关闭文件,显示到文本框里

encoding是用来改变打开文件时文件的打开格式,如utf-8等,没有这个会报错

我还加了一个错误判断,用来识别用户是不是捣乱了,打开了笔记本无法打开的文件

8)方法save

save用来保存文件,准确的说是save as另存为

asksaveasfilename也是easygui中的一个函数,它用来返回用户想保存的路径

open(a,'w')中的w是指“写”形式打开文件,如果文件不存在,会自动创建。打开以后,会清空文件的所有内容,写出代码里想要有的内容

写完文件之后把self.ss改成True就行了

9)方法clear

清屏的方法

self.text.delete是用来清空文本框一部分的内容

第一个参数是几行,几列,第二个也是,但是可以填写'end',用来表示到最后

所以1.0到end就是清到最后了

10)方法clo

用来最小化窗口

Tk.iconify是最小化窗口的方法

11)方法ex

用来关闭窗口

Tk.destroy是关闭窗口的方法

12)方法pasts

其实我当时不想和paste重名,所以我就写了pasts

用来粘贴文本

13)方法copy

用来复制文本框选中的内容

14)方法cut

用来剪切文本框选中的内容

15)方法undo

用来撤销文本框中的操作

16)方法redo

用来恢复文本框中的操作

17)方法eve

之前我在menu方法的结尾写了这行代码:

windnd.hook_dropfiles(self.win,func=self.eve)

用来检测有没有文件被拖拽到窗口范围里,绑定的触发函数是self.eve

这个函数用来打开拖拽的文件,获取其内容,并呈现到文本框里

由于windnd.hook_dropfiles对绑定的触发函数会返回一个值,所以files就是那个值,用来当作拖拽文件的路径

感叹!windnd创始人牛!牛!再牛!鼓掌!

但是读文件前,要把这个one year搞成gbk格式的,不然读不了

读完之后,就可以把他显示到文本框里了

18)方法pos

我在前面绑定了pos方法,把它当作get文本框中光标位置的函数,并写出来

Text.index('insert')就是获取文本框里光标的位置的方法,再把它改到工具栏的Label里,就行了

注意,这里的光标不是鼠标箭头,而是文本框中一闪一闪,被视作写文本的地方的光标

19)方法me

Menu类有一个特别的方法,叫post,用来把菜单显示到某个位置,而event是bind提供综合信息的参数,event.x_root和event.y_root就是光标的xy位置

这个方法就是用来添加一个右键菜单(和edit菜单一样)

20)方法bc

这方法用来在关闭窗口时询问用户保不保存,保存就self.save(),不保存就直接关了

21)方法edd

用来改变文字颜色,这玩意的tag有点复杂,做出如下解释

Text.tag_add就是添加一个tag,第一个参数为tag名,第二个参数为tag颜色起始位置,第三个参数为tag颜色终止位置

Text.tag_config就是“激活”tag,将tag显示出来。第一个参数就是tag名,第二个参数是tag颜色

22)方法find

用来查找某个字符串的位置。其中,Text.search就是查找字符串在哪的函数

第一个参数是要查找的字符串,第二个参数是查找的起始范围,stopindex就是查找的终止范围,可以写'end'

23)方法hlp

此处是help的缩写,提供一个小窗口,写着作者信息

是不是很详细?好了,本文章的内容就到这里,感谢大家的收听,观众们洗洗睡吧!

非喜勿喷!!