import tkinter as tk
from tkinter import filedialog
class MyTextEditor:
def __init__(self,master):
self.master=master
self.master.title("我的文本编辑器")
self.master.geometry('900x700')
self.creat_menu()
self.create_textbox()
def creat_menu(self):
MyMenu=tk.Menu(self.master)
MyFileMenu=tk.Menu(MyMenu,tearoff=0)#不让子菜单离开菜单栏
MyEditorMenu=tk.Menu(MyMenu,tearoff=0)
MyFileMenu.add_command(label='新建一个文件',command=self.My_new_file)#创建子菜单的选项,会调用command后面的函数
MyFileMenu.add_command(label='打开已有文件',command=self.My_open_file)
MyFileMenu.add_command(label='保存这个文件',command=self.My_save_file)
MyFileMenu.add_separator()#增加分隔符
MyFileMenu.add_command(label='退出这个编辑器',command=self.master.quit)
MyEditorMenu.add_command(label='查找指定内容',command=self.My_find)
MyEditorMenu.add_command(label='替换指定内容',command=self.replace)
MyEditorMenu.add_separator()
MyEditorMenu.add_command(label='插入文本块',command=self.insert_textblock)
MyEditorMenu.add_command(label='插入文本串',command=self.insert_text)
MyEditorMenu.add_separator()
MyEditorMenu.add_command(label='删除内容',command=self.delete)
MyEditorMenu.add_separator()
MyEditorMenu.add_command(label='移动行块',command=self.move_lineblock)
MyEditorMenu.add_command(label='移动列块',command=self.move_columnblock)
MyMenu.add_cascade(label='文件操作',menu=MyFileMenu)
MyMenu.add_cascade(label='文本操作',menu=MyEditorMenu)
self.master.config(menu=MyMenu)
# #创建文本框
# def create_textbox(self):
# My_scrollbar=tk.Scrollbar(self.master)
# My_scrollbar.pack(side=tk.RIGHT,fill=tk.Y)#创建滚动条,将位置放在窗口右侧,滚动方向为Y轴(垂直)方向
# self.textbox=tk.Text(self.master,wrap=tk.WORD,yscrollcommand=My_scrollbar.set)#以单词为为分割符
# self.textbox.pack(fill=tk.BOTH, expand=1)
# My_scrollbar.config(command=self.textbox.yview)#将滑动绑定文本内容
def create_textbox(self):
textbox_frame = tk.Frame(self.master)
textbox_frame.pack(fill=tk.BOTH, expand=1)
scrollbar = tk.Scrollbar(textbox_frame)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.textbox = tk.Text(textbox_frame, wrap=tk.WORD, yscrollcommand=scrollbar.set)
self.textbox.pack(fill=tk.BOTH, expand=1)
self.line_numbers = tk.Text(textbox_frame, width=5, state=tk.DISABLED)
self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
scrollbar.config(command=self.textbox.yview)
self.textbox.bind("<<Modified>>", self.update_line_numbers)
self.textbox.bind("<KeyRelease>", self.update_line_numbers) # 绑定 KeyRelease 事件
self.update_line_numbers()
def update_line_numbers(self, event=None):
content = self.textbox.get("1.0", tk.END)
line_count = content.count("\n") + 1
line_numbers_text = "\n".join(str(i) for i in range(1, line_count + 1))
self.line_numbers.config(state=tk.NORMAL)
self.line_numbers.delete("1.0", tk.END)
self.line_numbers.insert(tk.END, line_numbers_text)
self.line_numbers.config(state=tk.DISABLED)
#
#文件操作函数
#
def My_new_file(self):
self.textbox.delete('1.0', tk.END)#从最后一个删到第一个
def My_open_file(self):
filepath = filedialog.askopenfilename()#打开文件
#将文件全都存到data中,然后将这些都删除,再插入数据
with open(filepath, 'r') as f:
data = f.read()
self.textbox.delete('1.0', tk.END)
self.textbox.insert(tk.END, data)
def My_save_file(self):
#调用函数保存函数,默认保存为txt文件
filepath = filedialog.asksaveasfilename(defaultextension='.txt')
data = self.textbox.get('1.0', tk.END)
with open(filepath, 'w') as f:
f.write(data)
#
#文本操作函数
#
#查找内容
def My_find(self):
NeedWord=tk.simpledialog.askstring('查找', '请输入要查找的内容')
#从最开始找,找到后贴上found标签,将start和end交换,继续往后找
if NeedWord:
start = '1.0'
while True:
start = self.textbox.search(NeedWord, start, tk.END)
if not start:
break
end = '{}+{}c'.format(start, len(NeedWord))
self.textbox.tag_add('found', start, end)
start = end
self.textbox.tag_config('found', foreground='white', background='blue')
# 替换
def replace(self):
target = tk.simpledialog.askstring('替换', '请输入要替换的内容')
need = tk.simpledialog.askstring('替换', '请输入替换的内容')
if target:
start = '1.0'
while True:
start = self.textbox.search(target, start, tk.END)
if not start:
break
end = '{}+{}c'.format(start, len(target))
self.textbox.tag_add('found', start, end)
start = end
found_range = '1.0'
while True:
found_range = self.textbox.tag_nextrange('found', found_range)
if not found_range:
break
replace_str = need
self.textbox.delete(found_range[0], found_range[1])
self.textbox.insert(found_range[0], replace_str)
if self.textbox.tag_ranges('found'):
self.textbox.tag_remove('found', '1.0', tk.END)
else:
tk.messagebox.showinfo('未找到匹配项', '未找到任何匹配的内容')
# 插入文本块
def insert_textblock(self):
# 可以获取到一个包含选中文本起始位置和结束位置的元组将起始位置和结束位置分别赋值给 start 和 end 变量。
start, end = self.textbox.tag_ranges(tk.SEL)
if start and end:
data = self.textbox.get(start, end)
self.textbox.delete(start, end)
self.textbox.mark_set(tk.INSERT, start)#将插入光标的位置设置为 start
self.textbox.insert(tk.INSERT, data)#在光标处插入数据
# 插入文本串
def insert_text(self):
data = tk.simpledialog.askstring('插入文本', '请输入要插入的内容')
if data:
self.textbox.insert(tk.INSERT, data)
# 删除
def delete(self):
start, end = self.textbox.tag_ranges(tk.SEL)
if start and end:
self.textbox.delete(start, end)
# 移动行块
def move_lineblock(self):
start, end = self.textbox.tag_ranges(tk.SEL)
if start and end:
data = self.textbox.get(start, end)
self.textbox.delete(start, end)
insert_index = self.get_insert_index()
self.textbox.mark_set(tk.INSERT, insert_index)
self.textbox.insert(insert_index, data)
# 移动列块
def move_columnblock(self):
selected_ranges = self.textbox.tag_ranges(tk.SEL)
if len(selected_ranges) % 2 != 0:
tk.messagebox.showinfo('无效的选择', '无法移动列块:请选择完整的文本行')
return
for i in range(0, len(selected_ranges), 2):
start = selected_ranges[i]
end = selected_ranges[i + 1]
start_line, start_col = map(int, start.split('.'))
end_line, end_col = map(int, end.split('.'))
data = ''
for line in range(start_line, end_line + 1):
line_data = self.textbox.get('{}.{}'.format(line, start_col), '{}.{}'.format(line, end_col))
data += line_data + '\n'
self.textbox.delete(start, end)
insert_index = self.get_insert_index()
self.textbox.mark_set(tk.INSERT, insert_index)
self.textbox.insert(insert_index, data)
# 获取插入点位置
def get_insert_index(self):
insert_line, insert_col = map(int, self.textbox.index(tk.INSERT).split('.'))
total_lines = int(self.textbox.index(tk.END).split('.')[0])
if insert_line == total_lines:
return '{}.{}'.format(insert_line + 1, 0)
else:
return '{}.{}'.format(insert_line, 0)
root=tk.Tk()
app=MyTextEditor(root)
root.mainloop()