编辑菜单选项栏事件功能实现

  • 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_text函数的设置,注意事项:

① 使用查找命令后就会弹出一个小窗体,而且是要显示在主窗口之上的

② 查找窗口的布局设置,采用网格式布局的方式较为简洁(简单)

③ 如何实现文本数据的查找,这里单独再定义一个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)】编辑菜单选项栏事件和右键菜单功能实现(撤销、还原、复制、粘贴、剪切、查找及全选)相关推荐

  1. Linuxqt制作文本编辑器_Python实操!速收藏!学习使用Python创建文本编辑器应用程序

    朋友们,大家好,这次再次与作者见面,作者将发表一篇文章,介绍如何使用Python Tkinter创建文本编辑器.Tkinter是一个Python库,在您想要创建应用程序时非常有用. 立即讨论如何制作此 ...

  2. java记事本复制粘贴_Java Swing 如何实现记事本中“编辑”菜单下的 剪切,复制,粘贴,删除,全选 功能...

    这篇文字将要学习以下知识点: 1.如何给JButton按钮添加鼠标点击事件监听器 #1.addMouseListener(MouseListener l)  给JButton添加一个鼠标点击监听器l ...

  3. tkinter 中给某个文本加上滚动条_Python Tkinter自制文本编辑器

    本篇为视频课程 tkinter从入门到实战视频​blog.csdn.net 章节文档,请结合教程学习 4.1 自制编辑器 项目实战要点 在之前章节中已经学习了tkinter的大量知识,但仍然有部分知 ...

  4. python tkinter 自制文本编辑器

    成品如图: 代码 from tkinter import * from tkinter import filedialog from tkinter import messagebox import ...

  5. 用python制作文本编辑器

    import tkinter import tkinter as tk from tkinter import * import tkinter.filedialog import tkinter.m ...

  6. Mac自带文本编辑器TextEdit编辑大文件后打不开

    前段时间用Mac自带文本编辑器编辑文本.把一段超过十万行的excel文本粘贴进去,然后就看着小圈圈转啊转-进入漫长等待,最后无奈command+Q.之后再打开文本编辑器都是直接提示崩溃,然后尝试重装这 ...

  7. python tkinter实现文本编辑器

    题目 请设计并实现一款文本编辑器.程序允许用户打开.保存文本文件. 例如: 在用户打开文件时,会呈现打开文件对话框, 在用户保存文件时,会呈现保存为对话框 当打开文件出错时,程序不会崩溃,而是会提示错 ...

  8. 2023.04.27 QT 制作文本编辑器

    有改变字体.颜色.打开文件以及保存文件功能 一.代码部分: 1. 头文件: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #inc ...

  9. java代码实现看帖回帖功能_求助Java窗口菜单如何实现复制粘贴剪切等功能(内附源代码)...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 if(e.getActionCommand()=="进入注册") {new CommFrame();   }}class Handle ...

最新文章

  1. 使用BCH 操作码的三个新型应用程序
  2. 第二章课下测试补交博客
  3. POJ - 1087 A Plug for UNIX(最大流)
  4. Django---启动admin的报no such table: auth_user错误
  5. Python filecmp库
  6. 百度远场语音识别套件-开箱评测
  7. 关于BASYS3给初学者的建议(有关引脚的书写
  8. 信息系统项目管理师必背核心考点(二十六)三点估算(PERT)
  9. PA AE PR AI 2019注册机
  10. 通过第三方平台超级鹰进行登录页面验证码识别
  11. html 英文自动换行,CSS解决英文自动换行有关问题
  12. SNS过早收费扼杀用户成长
  13. 怎样在JavaScript添加图片
  14. 通过日期的相减计算年龄
  15. Ubuntu18.04 编译Android 10源码 并烧录源码到pixel3的避坑指南
  16. 焦距 对焦 变焦--摄影基础理论(3)
  17. 阿里巴巴2016 实习生招聘练习题(二)
  18. XPS如何在线批量转换成PDF
  19. java毕业生设计兴澜幼儿园管理系统计算机源码+系统+mysql+调试部署+lw
  20. BN、LN、IN、GN的区别

热门文章

  1. C语言小游戏,三子棋游戏(适合初学者练习)
  2. bcedit双系统更改启动项名称_bcdedit添加win7启动项
  3. 应届生:求职必看的十部电影
  4. 关于人脉这个事情:你若盛开,蝴蝶自来
  5. 线程池的种类有哪些?
  6. adb push fail
  7. 【unity shader/风格化水表面渲染/基础笔记】urp代码版02-岸边泡沫的生成
  8. 脑图XMind 8免费激活方法
  9. 大学考试分数越高学分越多吗_大学学分绩点有多重要,你在意过吗?
  10. 在破公司上班的最后一天,老板让我给他开发一个拨号程序——初级版(Java实现)