【tkinter制作文本编辑器(3)】编辑菜单选项栏事件和右键菜单功能实现(撤销、还原、复制、粘贴、剪切、查找及全选)
编辑菜单选项栏事件功能实现
- 1. 编辑菜单选项栏事件功能实现步骤
- 1.1 撤销
- 1.2 恢复
- 1.3 剪切
- 1.4 复制
- 1.5 粘贴
- 1.6 全选
- 1.7 查找
- 2. 快捷键绑定
- 3. 右键弹出菜单设置
- 4. 全部代码
1. 编辑菜单选项栏事件功能实现步骤
上一个博客完成了“文件”菜单栏下关联内容的功能设置,接着该进行“编辑”菜单栏下的关联内容的功能设置。
Tk
里面已经包含了很多的event
事件,上一个博客的自定义函数时候会发现有个参数event = None
(没有使用自带的event
事件),这里可以使用event_generate
这个方法用来产生相应的事件(就不需要分别自定义函数了),具体包含的event事件种类见官网。具体的设置内容如下
1.1 撤销
撤销就是返回上一步的意思,取消对刚刚操作的执行。为了方便调用,这里直接将下面所有的功能封装在一个函数中,通过一个参数action_type
进行传递,可以节省大量代码,减少工作量
注意:这里调用的函数中含有参数,可以使用lambda
函数进行参数传递
edit_menu.add_command(label='撤销', accelerator='Ctrl+Z', command=lambda: self.handle_menu_action('撤销'))
def handle_menu_action(self, action_type):if action_type == "撤销":self.content_text.event_generate("<<Undo>>")
→ 输出的结果为:(撤销功能设置完毕,快捷键Tk
自带有为Ctrl+z/Z
)
1.2 恢复
恢复功能和上面的撤销功能相反,设置代码如下
edit_menu.add_command(label='恢复',accelerator = 'Ctrl+Y',command = lambda : self.handle_menu_action('恢复'))
def handle_menu_action(self, action_type):if action_type == "恢复":self.content_text.event_generate("<<Redo>>")
→ 输出的结果为:(恢复功能设置完毕,快捷键Tk
自带有为Ctrl+y/Y
)
1.3 剪切
剪切就是将所选中的文本数据内容,默认然后移动到目标位置(原位置的内容消失),设置如下
edit_menu.add_command(label='剪切',accelerator = 'Ctrl+X',command = lambda : self.handle_menu_action('剪切'))
def handle_menu_action(self, action_type):if action_type == "剪切":self.content_text.event_generate("<<Redo>>")
→ 输出的结果为:(剪切功能设置完毕,快捷键Tk
自带有为Ctrl+x/X
)
1.4 复制
复制就是将所选中的文本数据内容,默认然后移动到目标位置(原位置的内容不消失),设置如下
edit_menu.add_command(label='复制',accelerator = 'Ctrl+C',command = lambda : self.handle_menu_action('复制'))
def handle_menu_action(self, action_type):if action_type == "复制":self.content_text.event_generate("<<Copy>>")
→ 输出的结果为:(剪切功能设置完毕,快捷键Tk
自带有为Ctrl+c/C
)
1.5 粘贴
粘贴就是复制或者剪切文本后要将文本放置在一个位置,以上都是默认使用了粘贴,设置如下
edit_menu.add_command(label='粘贴',accelerator = 'Ctrl+V',command = lambda : self.handle_menu_action('粘贴'))
def handle_menu_action(self, action_type):if action_type == "粘贴":self.content_text.event_generate("<<Paste>>")
→ 输出的结果为:(粘贴功能设置完毕,快捷键Tk
自带有为Ctrl+v/V
)
1.6 全选
全选功能就是对于文本栏中所有的文本数据进行选中,然后可以进行其他功能的操作,比如复制,剪切等,设置如下
edit_menu.add_command(label='全选',accelerator = 'Ctrl+A',command = lambda : self.handle_menu_action('全选'))
def handle_menu_action(self, action_type):if action_type == "全选":self.content_text.event_generate("<<SelectAll>>")
→ 输出的结果为:(全选功能设置完毕,快捷键Tk
自带有为Ctrl+a/A
)
1.7 查找
查找功能就是在文本栏中进行相关信息的匹配,最后输出满足的数据所在的位置。这个事件在Tk
里面并没有现成的可以直接加载,因此需要和之前一样进行自定义函数顺带绑定一下快捷键(没有快捷键,就需要自己设置),设置如下
edit_menu.add_command(label='查找', accelerator='Ctrl+F', command=self.find_text)
self.content_text.bind('<Control-f>', self.find_text)#该语句是在_create_body_函数内部
self.content_text.bind('<Control-F>', self.find_text)#该语句是在_create_body_函数内部
核心重点在于find_tex
t函数的设置,注意事项:
① 使用查找命令后就会弹出一个小窗体,而且是要显示在主窗口之上的
② 查找窗口的布局设置,采用网格式布局的方式较为简洁(简单)
③ 如何实现文本数据的查找,这里单独再定义一个search_result
搜索结果的函数,直接调用
④ 搜索框的关闭,因为是子窗口,在任务结束之后需要关闭的
def find_text(self,event=None):search_toplevel = Toplevel(self) #创建一个顶级窗口search_toplevel.title('查找文本') #窗口命名search_toplevel.transient(self) #总是让搜索框显示在主程序窗口之上search_toplevel.geometry('340x60+700+500') #设置查找框所在的位置search_toplevel.resizable(False, False) #窗口不可变Label(search_toplevel,text='查找全部:').grid(row=0,column=0,sticky='e') #设置标签提醒search_entry_widget = Entry(search_toplevel,width=25) #设置输入框search_entry_widget.grid(row=0,column=1,padx=2,pady=2,sticky='we') #布局search_entry_widget.focus_set() #这里就是输入的焦点,如果没有的话就没有提示输入的一闪一闪的竖杠ignore_case_value = IntVar() #这里的整型变量只在这个函数内部使用所以不需要转化为实例属性Checkbutton(search_toplevel, text='忽略大小写', variable=ignore_case_value).grid(row=1, column=1, sticky='e', padx=2, pady=2) #设置是否忽略大小写的按钮Button(search_toplevel, text="查找", command=lambda: self.search_result(search_entry_widget.get(), ignore_case_value.get(), search_toplevel, search_entry_widget) ).grid(row=0, column=2, sticky='e' + 'w', padx=2, pady=2) #设置查找按钮,但是要回事件的,中间常常的参数是要传入到search_result函数中的变量def close_search_window():self.content_text.tag_remove('match', '1.0', "end") #首先移除所有的标记效果,因为是选择文本内容是要标记出来选中的内容,所以在退出窗口之前,选中的标记需要先去除掉search_toplevel.destroy() #然后再销毁窗口search_toplevel.protocol('WM_DELETE_WINDOW', close_search_window) #最后这个窗口也需要关闭,只是不需要弹出消息对话框,所以需要重新定一个函数,这个函数在find_text内部定义的话,较为简单,#如果和主窗口退出时定义的那样需要将search_toplevel变量转化为实例属性,这样就可以在另外的函数中使用了return "break" #防止一直被使用,每次运行之后要退出
search_result
函数讲解,传入的四个参数,分别为:搜索的关键词,是否忽略大小写,搜索窗口(用来在标题处显示搜索成功的结果),搜索栏(用来显示输入的焦点)。注意事项
① 匹配文本后,做标记(颜色设置)
② 匹配文本计数(大小写的问题)
③ 多文本数据匹配(不是一个字符数据的匹配)
def search_result(self, key, ignore_case, search_toplevel, search_box):self.content_text.tag_remove('match', '1.0', "end") #每次进行匹配文本内容查找时候都要把上一次匹配的标记给去掉#print(ignore_case)#不勾选的话就是0,默认不忽略matches_found = 0 #匹配成功计数if key: #如果输入了要匹配的数据,进行接下来的操作start_pos = '1.0' #将匹配开始的位置设置在文本开始的位置while True:# search返回第一个匹配上的结果的开始索引,返回空则没有匹配的(nocase:忽略大小写)start_pos = self.content_text.search(key, start_pos, nocase=ignore_case, stopindex="end") #这里直接使用文本栏的搜索功能,需要输入要匹配的数据,开始和结束的位置,以及是否忽略大小写,可以使用01代替,这也就是之前为啥要进行整型变量的赋值了if not start_pos:break #这两个组合就是,如果匹配到了就继续往下,没有匹配到就退出while循环end_pos = '{}+{}c'.format(start_pos, len(key)) #经过上面的另个语句,可知匹配到内容了,这时候就要把匹配结束的位置记下来self.content_text.tag_add('match', start_pos, end_pos)#这里就用到了上面的位置,对匹配到的内容进行贴标签matches_found += 1 #匹配的内容计数+1start_pos = end_pos #这时候要为下一次循环做准备,所以先把开始的位置定在上一次匹配成功的数据结束的位置,继续进行下去self.content_text.tag_config('match', foreground='red', background='yellow') #进行标签的配色search_box.focus_set() #显示焦点search_toplevel.title('发现%d个匹配的' % matches_found) #在标题上显示匹配结果
→ 输出的结果为:(文本查找的功能满足)
2. 快捷键绑定
由上面的设置可知,撤销、回复、剪切、复制、粘贴、全选,在创建文本栏的时候Tk中是默认快捷键的,而且这种快捷键也是我们日常生活中经常使用到的,关于自定义的find_text
函数,上面也进行了快捷的设置,因此关于快捷键的设置这里相当于完成了。这里的快捷键设置,是对应之前设置的快捷菜单栏的,也就是点击小图标可以响应对应的时间,设置如下
def _create_shortcut_bar_(self):shortcut_bar = Frame(self, height=25, background='#20b2aa')shortcut_bar.pack(fill='x')for i, icon in enumerate(ICONS):tool_icon = PhotoImage(file='img/%s.gif' % (icon,))tool_btn = Button(shortcut_bar, image=tool_icon,command=self._shortcut_action(icon))#和之前的区别在于这里添加一个函数回调 ,这个函数在下面邮件弹出菜单设置的时候也有用到,总共九个功能tool_btn.pack(side='left')self.icon_res.append(tool_icon)
→ 输出的结果为:(_shortcut_action
函数在下面的右键弹出设置)
3. 右键弹出菜单设置
在文本编辑器中,右键弹出菜单功能可以简单的将上面实现的功能进行融合,方便在输入时候进行快速调用,这里主要的注意事项是:
① 右键弹出是要在鼠标选定的位置弹出
② 参数传递的过程(不用lambda
了,减少代码量,可以使用函数递包的方式)
③ 需要在类的初始化创建self._create_right_popup_menu()
函数
def _create_right_popup_menu(self):popup_menu = Menu(self.content_text, tearoff=0) #有了之间创建菜单的经历,这里就是依托的对象不同for it1, it2 in zip(['剪切', '复制', '粘贴', '撤销', '恢复'],['cut', 'copy', 'paste', 'undo', 'redo']):popup_menu.add_command(label=it1, compound='left',command=self._shortcut_action(it2))#注意这里,使用的label是汉字的,传到函数中的参数是英文的,这里其实可以直接全部使用中文的popup_menu.add_separator() #为了美观,将全选这个功能单独提取出来popup_menu.add_command(label='全选', command = lambda: self.handle_menu_action("全选"))self.content_text.bind('<Button-3>',lambda event: popup_menu.tk_popup(event.x_root, event.y_root))#实现在右键点击后出现弹窗
函数递包(这里没有再使用lambda
传参,可以像设置‘全选’功能键一样,将其他的功能键进行类似设置),实现不用lambda
就可以传递参数
def _shortcut_action(self, type):def handle():if type == "new_file":self.new_file()elif type == "open_file":self.open_file()elif type == "save":self.save()elif type == "cut":self.handle_menu_action("剪切")elif type == "copy":self.handle_menu_action("复制")elif type == "paste":self.handle_menu_action("粘贴")elif type == "undo":self.handle_menu_action("撤销")elif type == "redo":self.handle_menu_action("恢复")elif type == "find_text":self.find_text()return handle #最后返回的是就是handle对象
→ 输出的结果为:(右键弹出菜单设置完毕)
4. 全部代码
该部分实现功能的全部代码
def _create_menu_bar_(self):menu_bar = Menu(self)edit_menu = Menu(menu_bar,tearoff = 0) #基于菜单栏实例化“编辑”关联选项栏对象edit_menu.add_command(label='撤销',accelerator = 'Ctrl+Z',command = lambda : self.handle_menu_action('撤销'))edit_menu.add_command(label='恢复',accelerator = 'Ctrl+Y',command = lambda : self.handle_menu_action('恢复'))edit_menu.add_separator()edit_menu.add_command(label='剪切',accelerator = 'Ctrl+X',command = lambda : self.handle_menu_action('剪切'))edit_menu.add_command(label='复制',accelerator = 'Ctrl+C',command = lambda : self.handle_menu_action('复制'))edit_menu.add_command(label='粘贴',accelerator = 'Ctrl+V',command = lambda : self.handle_menu_action('粘贴'))edit_menu.add_separator()edit_menu.add_command(label='全选',accelerator = 'Ctrl+A',command = lambda : self.handle_menu_action('全选'))edit_menu.add_separator()edit_menu.add_command(label='查找',accelerator = 'Ctrl+F',command = self.find_text)menu_bar.add_cascade(label='编辑',menu=edit_menu) def _create_body_(self):self.content_text.bind('<Control-F>', self.find_text)self.content_text.bind('<Control-f>', self.find_text)def _create_right_popup_menu(self):popup_menu = Menu(self.content_text, tearoff=0)for it1, it2 in zip(['剪切', '复制', '粘贴', '撤销', '恢复'],['cut', 'copy', 'paste', 'undo', 'redo']):popup_menu.add_command(label=it1, compound='left',command=self._shortcut_action(it2))popup_menu.add_separator()popup_menu.add_command(label='全选', command = lambda: self.handle_menu_action("全选"))self.content_text.bind('<Button-3>',lambda event: popup_menu.tk_popup(event.x_root, event.y_root))def _shortcut_action(self, type):def handle():if type == "cut":self.handle_menu_action("剪切")elif type == "copy":self.handle_menu_action("复制")elif type == "paste":self.handle_menu_action("粘贴")elif type == "undo":self.handle_menu_action("撤销")elif type == "redo":self.handle_menu_action("恢复")elif type == "find_text":self.find_text()return handledef handle_menu_action(self, action_type):if action_type == "撤销":self.content_text.event_generate("<<Undo>>")elif action_type == "恢复":self.content_text.event_generate("<<Redo>>")elif action_type == "剪切":self.content_text.event_generate("<<Cut>>")elif action_type == "复制":self.content_text.event_generate("<<Copy>>")elif action_type == "粘贴":self.content_text.event_generate("<<Paste>>")elif action_type == "全选":self.content_text.event_generate("<<SelectAll>>")def find_text(self,event=None):search_toplevel = Toplevel(self) #创建一个顶级窗口search_toplevel.title('查找文本') #窗口命名search_toplevel.transient(self) #总是让搜索框显示在主程序窗口之上search_toplevel.geometry('340x60+700+500')search_toplevel.resizable(False, False) #窗口不可变Label(search_toplevel,text='查找全部:').grid(row=0,column=0,sticky='e')search_entry_widget = Entry(search_toplevel,width=25)search_entry_widget.grid(row=0,column=1,padx=2,pady=2,sticky='we')search_entry_widget.focus_set()ignore_case_value = IntVar()Checkbutton(search_toplevel, text='忽略大小写', variable=ignore_case_value).grid(row=1, column=1, sticky='e', padx=2, pady=2)Button(search_toplevel, text="查找", command=lambda: self.search_result(search_entry_widget.get(), ignore_case_value.get(), search_toplevel, search_entry_widget)).grid(row=0, column=2, sticky='e' + 'w', padx=2, pady=2)def close_search_window():self.content_text.tag_remove('match', '1.0', "end")search_toplevel.destroy()search_toplevel.protocol('WM_DELETE_WINDOW', close_search_window)return "break"def search_result(self, key, ignore_case, search_toplevel, search_box):self.content_text.tag_remove('match', '1.0', "end")print(ignore_case)#不勾选的话就是0,默认不忽略matches_found = 0if key:start_pos = '1.0'while True:# search返回第一个匹配上的结果的开始索引,返回空则没有匹配的(nocase:忽略大小写)start_pos = self.content_text.search(key, start_pos, nocase=ignore_case, stopindex="end")if not start_pos:breakend_pos = '{}+{}c'.format(start_pos, len(key))self.content_text.tag_add('match', start_pos, end_pos)matches_found += 1start_pos = end_posself.content_text.tag_config('match', foreground='red', background='yellow')search_box.focus_set()search_toplevel.title('发现%d个匹配的' % matches_found)
【tkinter制作文本编辑器(3)】编辑菜单选项栏事件和右键菜单功能实现(撤销、还原、复制、粘贴、剪切、查找及全选)相关推荐
- Linuxqt制作文本编辑器_Python实操!速收藏!学习使用Python创建文本编辑器应用程序
朋友们,大家好,这次再次与作者见面,作者将发表一篇文章,介绍如何使用Python Tkinter创建文本编辑器.Tkinter是一个Python库,在您想要创建应用程序时非常有用. 立即讨论如何制作此 ...
- java记事本复制粘贴_Java Swing 如何实现记事本中“编辑”菜单下的 剪切,复制,粘贴,删除,全选 功能...
这篇文字将要学习以下知识点: 1.如何给JButton按钮添加鼠标点击事件监听器 #1.addMouseListener(MouseListener l) 给JButton添加一个鼠标点击监听器l ...
- tkinter 中给某个文本加上滚动条_Python Tkinter自制文本编辑器
本篇为视频课程 tkinter从入门到实战视频blog.csdn.net 章节文档,请结合教程学习 4.1 自制编辑器 项目实战要点 在之前章节中已经学习了tkinter的大量知识,但仍然有部分知 ...
- python tkinter 自制文本编辑器
成品如图: 代码 from tkinter import * from tkinter import filedialog from tkinter import messagebox import ...
- 用python制作文本编辑器
import tkinter import tkinter as tk from tkinter import * import tkinter.filedialog import tkinter.m ...
- Mac自带文本编辑器TextEdit编辑大文件后打不开
前段时间用Mac自带文本编辑器编辑文本.把一段超过十万行的excel文本粘贴进去,然后就看着小圈圈转啊转-进入漫长等待,最后无奈command+Q.之后再打开文本编辑器都是直接提示崩溃,然后尝试重装这 ...
- python tkinter实现文本编辑器
题目 请设计并实现一款文本编辑器.程序允许用户打开.保存文本文件. 例如: 在用户打开文件时,会呈现打开文件对话框, 在用户保存文件时,会呈现保存为对话框 当打开文件出错时,程序不会崩溃,而是会提示错 ...
- 2023.04.27 QT 制作文本编辑器
有改变字体.颜色.打开文件以及保存文件功能 一.代码部分: 1. 头文件: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #inc ...
- java代码实现看帖回帖功能_求助Java窗口菜单如何实现复制粘贴剪切等功能(内附源代码)...
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 if(e.getActionCommand()=="进入注册") {new CommFrame(); }}class Handle ...
最新文章
- 使用BCH 操作码的三个新型应用程序
- 第二章课下测试补交博客
- POJ - 1087 A Plug for UNIX(最大流)
- Django---启动admin的报no such table: auth_user错误
- Python filecmp库
- 百度远场语音识别套件-开箱评测
- 关于BASYS3给初学者的建议(有关引脚的书写
- 信息系统项目管理师必背核心考点(二十六)三点估算(PERT)
- PA AE PR AI 2019注册机
- 通过第三方平台超级鹰进行登录页面验证码识别
- html 英文自动换行,CSS解决英文自动换行有关问题
- SNS过早收费扼杀用户成长
- 怎样在JavaScript添加图片
- 通过日期的相减计算年龄
- Ubuntu18.04 编译Android 10源码 并烧录源码到pixel3的避坑指南
- 焦距 对焦 变焦--摄影基础理论(3)
- 阿里巴巴2016 实习生招聘练习题(二)
- XPS如何在线批量转换成PDF
- java毕业生设计兴澜幼儿园管理系统计算机源码+系统+mysql+调试部署+lw
- BN、LN、IN、GN的区别