思路分析
1.首先是复制粘贴取消重做等功能,这些功能其实不用我 们去实现,因为tkinter 有内建的实现,我们只需要调用 一个函数即可。
2.对于打开新建保存另存为,就是考验我们读写文件的基本功了
3.对于查找,也是增加的唯一的一个比较复杂的功能,因 为它需要再建一个窗口,至于真正的查找,不用我们把文 本内容拿出来用正则去匹配然后再定位,官方有现成的 API。
代码思路步骤
文章结尾贴有完整代码和部分注释:
首先是创建界面以及文件菜单和编辑菜单:
然后是在创建一个“关于”菜单:
.然后是菜单命令的实现(它包括了需要导入的文件和作 者以及版权的菜单实现):
最后也是类似上面的函数的实现
完整代码及注释如下:
from tkinter import *
from tkinter.messagebox import * #弹出提示框的模块
from tkinter.filedialog import * #打开文件对话框,获取文件路径的模块
import os #有关文件夹的模块
root = Tk()
root.title('Carson 文本编辑器')
filename = ''
#在主窗口放置文本
textPad = Text(root,undo = True)
textPad.pack(expand = YES,fill = BOTH)
shortcutbar = Frame(root,height = 25,bg = 'light sea green')
shortcutbar.pack(expand = NO,fill = X)
lnlabel = Label(root,width = 2,bg = 'antique white')
lnlabel.pack(side = LEFT,anchor = 'nw',fill = Y)
scroll = Scrollbar(textPad)
textPad.config(yscrollcommand = scroll.set)
scroll.config(command = textPad.yview)
scroll.pack(side = RIGHT,fill = Y)
"""创建菜单栏"""
menubar = Menu(root)
def new():
global filename,textPad,root
root.title('这是个还未命名的文件')
filename = None
#清空文本
textPad.delete(1.0,END)
def myopen():
#因为需要修改到全局变量的值,需要加global关键字
global filename
default_dir = r'D:\python' #设置默认打开路径
#下面filename返回文件路径
#打开文件对话框并获取文件路径保存
filename = askopenfilename(title = u'选择文件',defaultextension = '.txt',initialdir = (os.path.expanduser(default_dir))) #tKinter模块的选择文件,后面的os函数是将其中特殊字符替换成目录
if filename == '':
filename=None
else:
root.title("Carson记事本--"+os.path.basename(filename)) #basename()是获取文件路径最后的文件名
#delete()函数中须为n.n小数形式,代表第n行第几个下标
textPad.delete(1.0,END)
f = open(filename,'r')
#向文本中显示文件中的字符串,同样,insert()中,表示从第一行第一个下标插入
textPad.insert(1.0,f.read())
#没有使用with,需要手动关闭
f.close()
def save():
global filename
try:
f = open(filename,'w')
#获取文本中的字符串
message = textPad.get(1.0,END)
f.write(message)
f.close()
except:
saveas()
def saveas():
global filename
#打开保存文件的文件对话框
f = asksaveasfilename(initialfile = '未命名.txt',defaultextension = '.txt') #打开文件对话框并获取文件路径保存
filename = f
fh = open(f,'w')
message = textPad.get(1.0,END)
fh.write(message)
fh.close()
root.title("Carson记事本--"+os.path.basename(filename))
def undo():
global textPad
textPad.event_generate("<<Undo>>")
def redo():
global textPad
textPad.event_generate("<<Redo>>")
def cut():
global textPad
textPad.event_generate("<<Cut>>")
def copy():
global textPad
textPad.event_generate("<<Copy>>")
def paste():
global textPad
textPad.event_generate("<<Paste>>")
def find():
global root
t = Toplevel(root)
t.title('查找')
t.geometry("260x60+200+250")
t.transient(root) #告诉root新建t窗口是暂时等待
Label(t,text = '查找').grid(row = 0,column = 0,sticky = W)
v = StringVar()
e = Entry(t,width = 20,textvariable = v)
e.grid(row =0,column = 1,padx = 2,pady = 2,sticky = 'we')
e.focus_set() #焦点聚集在此输入框
c = IntVar()
Checkbutton(t,text = '不区分大小写',variable = c).grid(row = 1,column = 1,sticky = E)
Button(t,text = '查找所有',command = lambda :search(v.get(),c.get(),textPad,t,e)).grid(row = 0,column = 2,sticky = 'e'+'w',padx = 2,pady =2)
def close_search():
textPad.tag_remove('match','1.0',END)
t.destroy()
t.protocol('WM_DELETE_WINDOW',close_search)
def search(needle,cssnstv,textPad,t,e):
textPad.tag_remove('match','1.0',END)
count = 0
if needle:
pos = '1.0'
while True:
pos = textPad.search(needle,pos,nocase = cssnstv,stopindex=END)
if not pos:
break
lastpos = pos +str(len(needle))
textPad.tag_add('match',pos,lastpos)
count +=1
pos = lastpos
textPad.tag_config('match',foreground = 'yellow',background = 'green')
e.focus_set()
t.title(str(count)+'个匹配')
#此函数用于鼠标右键显示菜单的
def popup(event):
global editmenu
editmenu.tk_popup(event.x_root,event.y_root)
def select_all():
global textPad
#tag_add():为指定的文本添加Tags
#tag_config():可以设置Tags的样式
textPad.tag_add('sel','1.0','end')
def author():
showinfo('Carson提示您','This is carson的文本编辑version1')
def copyright():
showinfo('Carson提示您','版权信息最终解释权归Carson!')
#创建Top文件菜单及其子菜单并绑定函数
filemenu = Menu(menubar)
filemenu.add_command(label = '新建',accelerator = 'Ctrl + N',command=new)
filemenu.add_command(label = '打开',accelerator = 'Ctrl + O',command = myopen)
filemenu.add_command(label = '保存',accelerator = 'Ctrl + S',command = save)
filemenu.add_command(label = '另存为',accelerator = 'Ctrl + Shift + S',command = saveas)
menubar.add_cascade(label = '文件',menu = filemenu)
#创建Top编辑菜单及其子菜单并绑定函数,同类之间用下分割线
editmenu = Menu(menubar)
editmenu.add_command(label = '撤销',accelerator = 'Ctrl + Z',command = undo)
editmenu.add_command(label = '重做',accelerator = 'Ctrl + Y',command = redo)
editmenu.add_separator()
editmenu.add_command(label = '剪切',accelerator = 'Ctrl + X',command = cut)
editmenu.add_command(label = '复制',accelerator = 'Ctrl + C',command = copy)
editmenu.add_command(label = '粘贴',accelerator = 'Ctrl + V',command = paste)
editmenu.add_separator()
editmenu.add_command(label = '查找',accelerator = 'Ctrl + F',command = find)
editmenu.add_command(label = '全选',accelerator = 'Ctrl + A',command = select_all)
menubar.add_cascade(label = '编辑',menu = editmenu)
#创建Top关于菜单及其子菜单并绑定函数
aboutmenu = Menu(menubar)
aboutmenu.add_command(label = '作者',command = author)
aboutmenu.add_command(label = '版权',command = copyright)
menubar.add_cascade(label = '关于',menu = aboutmenu)
#将前面的菜单绑定到顶部栏
root.config(menu = menubar)
#热键绑定
textPad.bind("<Control-N>",new)
textPad.bind("<Control-n>",new)
textPad.bind("<Control-O>",myopen)
textPad.bind("<Control-o>",myopen)
textPad.bind("<Control-S>",save)
textPad.bind("<Control-s>",save)
textPad.bind("<Control-A>",select_all)
textPad.bind("<Control-a>",select_all)
textPad.bind("<Control-F>",find)
textPad.bind("<Control-f>",find)
textPad.bind("<Button-3>",popup)
root.mainloop()
暂测试无误于 2020-07-30!!
效果图:
The End!!创作不易,欢迎点赞/评论!!