美文网首页python
Python Tkinter实战——自制文本编辑器

Python Tkinter实战——自制文本编辑器

作者: c067527d47c2 | 来源:发表于2019-04-26 14:30 被阅读185次

4.1 自制编辑器

编辑器预览

编辑器预览

项目实战要点

image
当然在学习Python的道路上肯定会困难,没有好的学习资料,怎么去学习呢? 学习Python中有不明白推荐加入交流群号:973783996 群里有志同道合的小伙伴,互帮互助, 群里有不错的视频学习教程和PDF!
在之前章节中已经学习了tkinter的大量知识,但仍然有部分知识是没有覆盖到的,换句话说,本教程并不是一本事无巨细的帮助文档,未提到的知识,我将在项目实战中列出,根据具体使用场景来学习。
  • 覆写窗口关闭事件

    1self.protocol('WM_DELETE_WINDOW', self.exit_editor)
    
  • 实现鼠标右键菜单

     1def _create_right_popup_menu(self):
     2  popup_menu = Menu(self.content_text, tearoff=0)
     3  for it1, it2 in zip(['剪切', '复制', '粘贴', '撤销', '恢复'],
     4                      ['cut', 'copy', 'paste', 'undo', 'redo']):
     5      popup_menu.add_command(label=it1, compound='left',
     6                             command=self._shortcut_action(it2))
     7      popup_menu.add_separator()
     8      popup_menu.add_command(label='全选', command=self.select_all)
     9      self.content_text.bind('<Button-3>',
    10                             lambda event: popup_menu.tk_popup(event.x_root, event.y_root))
    
  • 使用闭包处理回调事件

     1  def _shortcut_action(self, type):
     2      def handle():
     3          if type == "new_file":
     4              self.new_file()
     5          elif type == "open_file":
     6              self.open_file()
     7          elif type == "save":
     8              self.save()
     9          elif type == "cut":
    10              # ………… 省略部分条件判断
    11          if type != "copy" and type != "save":
    12              self._update_line_num()
    13      return handle
    
  • 使用tkinter中的定时回调

    1self.content_text.after(200, self._toggle_highlight)
    
  • 实现文本搜索功能

    1start_pos = self.content_text.search(key, start_pos, nocase=ignore_case, stopindex="end")
    

遗留待完善问题

  • 处理文本文件编码

    自制的编辑器目前无法打开不同编码格式的文本文件,需要能自动识别文本文件的编码

    建议考虑使用chardet 模块来识别编码

    1import chardet
    2
    3with open('xxx.py', 'rb') as file:
    4  print(chardet.detect(file.read(1024)))
    
  • 搜索框定位

    搜索框应当根据当前编辑器的相对位置来显示

    1# 获取根窗口的绝对位置,依据根窗口的位置计算搜索框的显示位置
    2print(self.winfo_rootx(), self.winfo_rooty())
    
  • 使用自定义的选项卡控件重构编辑器

    我们之前已经自定义了一个选项卡控件,实现了双创建选项卡,删除选项卡等功能,使用该控件重构编辑器,使编辑器更加实用

搭建 UI 框架

  1from tkinter import *
  2from tkinter.ttk import Scrollbar
  3
  4theme_color = {
  5    'Default': '#000000.#FFFFFF',
  6    'Greygarious': '#83406A.#D1D4D1',
  7    'Aquamarine': '#5B8340.#D1E7E0',
  8    'Bold Beige': '#4B4620.#FFF0E1',
  9    'Cobalt Blue': '#ffffBB.#3333aa',
 10    'Olive Green': '#D1E7E0.#5B8340',
 11    'Night Mode': '#FFFFFF.#000000',
 12}
 13
 14
 15class EditorPlus(Tk):
 16    def __init__(self):
 17        super().__init__()
 18        self._set_window_()
 19        self._create_menu_bar_()
 20        self._create_shortcut_bar_()
 21        self._create_body_()
 22
 23    # 设置初始窗口的属性
 24    def _set_window_(self):
 25        self.title("EditorPlus")
 26        self.geometry('650x450')
 27
 28    # 创建整个菜单栏
 29    def _create_menu_bar_(self):
 30        menu_bar = Menu(self)
 31        # 创建文件的联级菜单
 32        file_menu = Menu(menu_bar, tearoff=0)
 33        file_menu.add_command(label='新建', accelerator='Ctrl+N')
 34        file_menu.add_command(label='打开', accelerator='Ctrl+O')
 35        file_menu.add_command(label='保存', accelerator='Ctrl+S')
 36        file_menu.add_command(label='另存为', accelerator='Shift+Ctrl+S')
 37        file_menu.add_separator()
 38        file_menu.add_command(label='退出', accelerator='Alt+F4')
 39
 40        # 在菜单栏上添加菜单标签,并将该标签与相应的联级菜单关联起来
 41        menu_bar.add_cascade(label='文件', menu=file_menu)
 42
 43        # 创建编辑的联级菜单
 44        edit_menu = Menu(menu_bar, tearoff=0)
 45        edit_menu.add_command(label='撤销', accelerator='Ctrl+Z')
 46        edit_menu.add_command(label='恢复', accelerator='Ctrl+Y')
 47        edit_menu.add_separator()
 48        edit_menu.add_command(label='剪切', accelerator='Ctrl+X')
 49        edit_menu.add_command(label='复制', accelerator='Ctrl+C')
 50        edit_menu.add_command(label='粘贴', accelerator='Ctrl+V')
 51        edit_menu.add_separator()
 52        edit_menu.add_command(label='查找', accelerator='Ctrl+F')
 53        edit_menu.add_separator()
 54        edit_menu.add_command(label='全选', accelerator='Ctrl+A')
 55        menu_bar.add_cascade(label='编辑', menu=edit_menu)
 56
 57        # 视图菜单
 58        view_menu = Menu(menu_bar, tearoff=0)
 59        show_line_number = IntVar()
 60        show_line_number.set(1)
 61        view_menu.add_checkbutton(label='显示行号', variable=show_line_number)
 62
 63        highlight_line = IntVar()
 64        view_menu.add_checkbutton(label='高亮当前行', onvalue=1, offvalue=0, variable=highlight_line)
 65
 66        # 在主题菜单中再添加一个子菜单列表
 67        themes_menu = Menu(menu_bar, tearoff=0)
 68        view_menu.add_cascade(label='主题', menu=themes_menu)
 69
 70        theme_choice = StringVar()
 71        theme_choice.set('Default')
 72        for k in sorted(theme_color):
 73            themes_menu.add_radiobutton(label=k, variable=theme_choice)
 74
 75        menu_bar.add_cascade(label='视图', menu=view_menu)
 76
 77        about_menu = Menu(menu_bar, tearoff=0)
 78        about_menu.add_command(label='关于')
 79        about_menu.add_command(label='帮助')
 80        menu_bar.add_cascade(label='关于', menu=about_menu)
 81        self["menu"] = menu_bar
 82
 83    # 创建快捷菜单栏
 84    def _create_shortcut_bar_(self):
 85        shortcut_bar = Frame(self, height=25, background='#20b2aa')
 86        shortcut_bar.pack(fill='x')
 87
 88    # 创建程序主体
 89    def _create_body_(self):
 90        # 创建行号栏 (takefocus=0 屏蔽焦点)
 91        line_number_bar = Text(self, width=4, padx=3, takefocus=0, border=0,
 92                               background='#F0E68C', state='disabled')
 93        line_number_bar.pack(side='left', fill='y')
 94
 95        # 创建文本输入框
 96        content_text = Text(self, wrap='word')
 97        content_text.pack(expand='yes', fill='both')
 98
 99        # 创建滚动条
100        scroll_bar = Scrollbar(content_text)
101        scroll_bar["command"] = content_text.yview
102        content_text["yscrollcommand"] = scroll_bar.set
103        scroll_bar.pack(side='right', fill='y')
104
105
106if "__main__" == __name__:
107    app = EditorPlus()
108    app.mainloop()

完善编辑器的功能

实现了基本的界面框架之后,只需将相应的功能一个一个添加上去即可。

完整项目源码:https://github.com/arcticfox1919/tkinter-practice

相关文章

网友评论

    本文标题:Python Tkinter实战——自制文本编辑器

    本文链接:https://www.haomeiwen.com/subject/ubgfnqtx.html