本篇为视频课程 tkinter入门详解 章节对应文档,请结合视频学习,地址见文末
4.1 自制编辑器
项目实战要点
在之前章节中已经学习了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('',
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
课程地址
关注我的公众号:编程之路从0到1