python制作一个text文本文件

最终效果图

全部代码:

首先创建一个editor_style.py文件,做为程序调用的一些参数、变量使用,该文件的代码:

theme_color = {
    'Default': '#000000.#FFFFFF',
    'Greygarious': '#83406A.#D1D4D1',
    'Aquamarine': '#5B8340.#D1E7E0',
    'Bold Beige': '#4B4620.#FFF0E1',
    'Cobalt Blue': '#ffffBB.#3333aa',
    'Olive Green': '#D1E7E0.#5B8340',
    'Night Mode': '#FFFFFF.#000000',
}

#这里将快捷菜单栏上图表对应的名称存放列表中,和主题颜色参数放在一个py文件中,后面使用时候直接调用
ICONS = ['new_file', 'open_file', 'save', 'cut', 'copy', 'paste',
         'undo', 'redo', 'find_text']

接下来就是准备好文本文件会用到的各种图标文件
在这里插入图片描述

下面就是主程序的所有代码:

from tkinter import *  # 导入tkinter中的所有方法
from tkinter import filedialog,messagebox  # 导入文件操作模块和消息框,这两个模块需要单独导入
from tkinter.ttk import Scrollbar,Checkbutton,Label,Button # 导入ttk模块中指定的几个组件
import os # 导入系统模块
from editor_style import theme_color,ICONS # 导入editor_style文件中的两个变量


class EditorPlus(Tk):               # 继承 tkinter 类
    def __init__(self):             # 初始化 EditPlus 类
        super().__init__()          # 继承父类的初始化
        self._set_window_()         # 设置程序运行的主窗口,即调用运行类中的 _set_window 方法
        self._create_menu_bar_()    # 创建菜单组件
        self.icon_res=[]
        self.file_name = None
        self._create_shortcut_bar_()
        self._create_body_()
        self._create_right_popup_menu()

    def _set_window_(self):
        # 初始化窗口
        self.title('EditorPlus')                # 设置窗口名称
        scn_width, scn_height = self.maxsize()  #  获得程序运行设备显示器的分辨率
        wm_val = '750x450+{}+{}'.format((scn_width - 750) // 2, (scn_height - 450) // 2)
        self.geometry(wm_val)                   # 设备窗口大小并居中显示
        self.iconbitmap('img/editor.ico')       # 加载窗口左上方图标
        self.protocol('WM_DELETE_WINDOW', self.exit_editor)         # 设置窗口关闭提醒,调用 exit_editor 方法

    def _create_menu_bar_(self):
        ''' Create Menu Bar :return:No'''
        # 创建菜单栏
        menu_bar = Menu(self)   # 继承 Tk 的 Menu 对象 (一级菜单)

        # 文件菜单
        file_menu = Menu(menu_bar, tearoff=0)  # 基于菜单栏实例化(文件)关联选项栏对象,二级菜单
        file_menu.add_command(label='新建', accelerator='Ctrl+N', command=self.new_file)
        file_menu.add_command(label='打开', accelerator='Ctrl+O', command=self.open_file)
        file_menu.add_command(label='保存', accelerator='Ctrl+S', command=self.save)
        file_menu.add_command(label='另存为', accelerator='Ctrl+Shift+S', command=self.save_as)
        file_menu.add_separator()
        file_menu.add_command(label='退出', accelerator='Alt+F4', command=self.exit_editor)
        menu_bar.add_cascade(label="文件", menu=file_menu)  # 创建文件菜单栏

        # 编辑菜单
        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+F", command=self.find_text)
        edit_menu.add_separator()
        edit_menu.add_command(label='全选', accelerator="Ctrl+A", command=lambda: self.handle_menu_action('全选'))
        menu_bar.add_cascade(label="编辑", menu=edit_menu)

        view_menu = Menu(menu_bar, tearoff=0)
        self.is_show_line_number = IntVar()  # 设置变量,为后面 checkbutton类型的菜单提供变动属性
        self.is_show_line_number.set(1)      # 设置下面(显示行号)的初始台状态
        view_menu.add_checkbutton(label='显示行号', variable=self.is_show_line_number,command=self._update_line_num)

        self.highlight_line = IntVar()       # 设置变量,为后面 checkbutton类型的菜单提供变动属
        view_menu.add_checkbutton(label='高亮当前行', onvalue=1, offvalue=0, variable=self.highlight_line,command=self._toggle_highlight)

        # 在主题菜单中再添加一个子菜单
        theme_menu = Menu(menu_bar, tearoff=0)
        self.theme_choise = StringVar()   # 设置一个字符串变量,用来保存字符串
        self.theme_choise.set('Default')  # 初始化这个字符串的值
        for k in sorted(theme_color):  # 这里的theme_color 就是之前从editor_style导入的字典变量
            # 验证主题菜单的值,把字符串传到下面的 change_theme 方法中
            theme_menu.add_radiobutton(label=k, variable=self.theme_choise,command=self.change_theme)
        view_menu.add_cascade(label='主题', menu=theme_menu)  # 这里添加菜单指定的对象为 theme_menu
        menu_bar.add_cascade(label="视图", menu=view_menu)    # 这里添加视图菜单指定的对象为 view_menu

        # 一级菜单 “关于” 菜单,
        about_menu = Menu(menu_bar, tearoff=0)
        about_menu.add_command(label='关于',command=lambda :self.show_messagebox('关于'))
        about_menu.add_command(label='帮助',command=lambda :self.show_messagebox('帮助'))
        menu_bar.add_cascade(label="关于", menu=about_menu)

        self['menu'] = menu_bar     # 将菜单在程序的主窗口显示

    def show_messagebox(self, type):   # 这里是关于、帮助菜单点击时间弹出的消息框
        if type == '帮助':             # 判断点击选择的是帮助菜单
            messagebox.showinfo('帮助', '这是帮助文档!', icon='question')     # icon ='question' 消息框显示系统内置图标 question
        else:
            messagebox.showinfo('关于', 'EditorPlus_V0.1')

    def change_theme(self):     # 更新主题设置方法
        selected_theme= self.theme_choise.get()    # 获取用户选择的主题
        fg_bg = theme_color.get(selected_theme)    # 获取editor_style文件中的theme_color的对应值
        fg_color,bg_color = fg_bg.split('.')       # 以 “.” 为分隔符,获取两个字符串,分别赋值给两个变量 ('Default': '#000000.#FFFFFF')
        self.content_text.config(bg=bg_color,fg=fg_color)  # 设置 Text 的前景色和背景色

    def _toggle_highlight(self):     # 高亮显示方法
        if self.highlight_line.get():
            self.content_text.tag_remove('active_line',1.0,'end')
            self.content_text.tag_add('active_line','insert linestart','insert lineend+1c')
            self.content_text.after(200,self._toggle_highlight)
        else:
            self.content_text.tag_remove('active_line',1.0,'end')

    def _update_line_num(self): # 显示行号的方法
        if self.is_show_line_number.get():
            row,col=self.content_text.index('end').split('.')
            line_num_content="\n".join([str(i) for i in range(1,int(row))])
            self.line_number_bar.config(state='normal')
            self.line_number_bar.delete('1.0','end')
            self.line_number_bar.insert('1.0',line_num_content)
            self.line_number_bar.config(state='disabled')
        else:
            self.line_number_bar.config(state='normal')
            self.line_number_bar.delete('1.0', 'end')
            self.line_number_bar.config(state='disabled')

    def _create_shortcut_bar_(self):
        # 创建快捷菜单
        shortcut_bar = Frame(self, height=25, background='#20b2aa')     # 创建一个 Frame 放置快捷按钮
        shortcut_bar.pack(fill='x')     # 横向填充( x 轴方向 )

        for icon in ICONS:  # 遍历循环设置快捷按钮
            tool_icon = PhotoImage(file='img/{}.gif'.format(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)

    def _create_body_(self):
        # 创建行号栏(takefocus 屏蔽焦点 )
        self.line_number_bar = Text(self, width=4, padx=3, takefocus=0, border=0, background='#f0e68c',
                                    state='disabled')
        self.line_number_bar.pack(side='left', fill='y')

        # 创建文本输入框
        self.content_text = Text(self, wrap='word')
        self.content_text.pack(expand='yes', fill='both')

        # 创建滚动条
        scroll_baar = Scrollbar(self.content_text)
        scroll_baar['command'] = self.content_text.yview
        self.content_text['yscrollcommand'] = scroll_baar.set
        scroll_baar.pack(side='right', fill='y')

        # 设置快捷按键,绑定方法
        self.content_text.bind('<Control-N>', self.new_file)
        self.content_text.bind('<Control-n>', self.new_file)

        self.content_text.bind('<Control-O>', self.open_file)
        self.content_text.bind('<Control-o>', self.open_file)

        self.content_text.bind('<Control-S>', self.save)
        self.content_text.bind('<Control-s>', self.save)

        self.content_text.bind('<Control-Shift-S>', self.save_as)
        self.content_text.bind('<Control-Shift-s>', self.save_as)

        self.content_text.bind('<Control-F>', self.find_text)
        self.content_text.bind('<Control-f>', self.find_text)

        self.content_text.bind('<Alt-F4>', self.exit_editor)

        self.content_text.bind("<Any-KeyPress>", lambda e: self._update_line_num())
        self.content_text.tag_configure('active_line', background='#EEEEE0')

        self.bind_all('<KeyPress-F1>', lambda e: self.show_messagebox('帮助'))

    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 == "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()
            if type != 'copy' and type != 'save':
                self._update_line_num()

        return handle

    def new_file(self, event=None):
        # 新建功能模块函数
        self.title('New - EditorPlus')
        self.content_text.delete(1.0, END)
        self.content_name = None

    def open_file(self, event=None):
        # 创建打开菜单模块函数
        input_file = filedialog.askopenfilename(
            filetypes=[('所有文件', '*.*'), ('文本文件', '*.txt')]   # 弹出文件对话框,设置选择文件的类型
        )
        if input_file:  # 如果用户选择了文本,则进行打开
            # print(input_file)
            self.title('{} - EditorPlus'.format(os.path.basename(input_file)))  # 以文件的名称进行窗口标题的命名
            self.file_name = input_file     # 将这个打开的文件对象命名为其原来文件的名称
            self.content_text.delete(1.0, END)      # 删除当前文本内容中的数据
            with open(input_file, 'r') as file:
                self.content_text.insert(1.0, file.read())  # 将要打开文件中的数据写入到文本内容中

    def save(self, event=None):   # (保存方法)
        if not self.file_name:      # 这里就体现出来之前设置的 self.file_name 全局变量
            self.save_as()          # 没有文件名称的调用另存为
        else:
            self._write_to_file(self.file_name)  # 有文件名称的直接写入文件(保存)

    def save_as(self, event=None):      # 另存为方法
        input_file = filedialog.asksaveasfilename(   # 弹文件保存对话框
            filetypes=[('所有文件', '*.*'), ('文本文件', '*.txt')]
        )
        if input_file:          # 对用户操作进行判定
            self.file_name = input_file         # 设置文件名称
            self._write_to_file(self.file_name)     # 写入本地

    def _write_to_file(self, file_name):
        try:
            content = self.content_text.get(1.0, "end")   # 获取文本框中的所有数据
            with open(file_name, 'w') as file:
                file.write(content)             # 将数据写入到本地文件中
            self.title('%s - EditorPlus' % os.path.basename(self.file_name)) # 重置一下当前窗口名称
        except IOError:
            messagebox.showwarning('保存', '保存失败!')   # 如果保存失败的话,弹出对话框提示

    def 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>>')
        if action_type != "复制":
            self._update_line_num()

    def find_text(self):
        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, padx=2, pady=2, sticky='e'
        )
        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, padx=2, pady=2, sticky='ew')

        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')
        matches_found = 0
        if key:
            start_pos = '1.0'
            while True:
                start_pos = self.content_text.search(key,start_pos,nocase=ignore_case,stopindex='end')
                if not start_pos:
                    break
                end_pos = '{}={}c'.format(start_pos,len(key))
                self.content_text.tag_add('match',start_pos,end_pos)
                matches_found += 1
                start_pos = end_pos
            self.content_text.tag_config('match',foreground='red',background='yellow')
        search_box.focus_set()
        search_toplevel.title("发现%d个匹配的"%matches_found)

    def exit_editor(self):
        # 退出验证
        if messagebox.askokcancel("退出?",'确定退出吗?'):  # 设置文本提醒,弹出消息框
            self.destroy()          # 满足条件的话,主窗口退出

if __name__ == '__main__':
    app = EditorPlus()   # 实例化类
    app.mainloop()       # 保持显示窗口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面我给你介绍一下用 Python 制作一个微型文本编辑器的方法。 首先,我们可以使用 Python 自带的 tkinter 模块来创建 GUI 界面。然后,我们需要在界面上添加一个文本框用于输入和显示文本,还需要添加一些按钮用于实现编辑操作,如保存、打开、剪切、复制和粘贴等。 具体实现步骤如下: 1. 导入 tkinter 模块: ```python import tkinter as tk from tkinter import filedialog ``` 2. 创建主窗口和文本框: ```python root = tk.Tk() text = tk.Text(root) text.pack() ``` 3. 添加菜单栏和菜单项: ```python menu_bar = tk.Menu(root) file_menu = tk.Menu(menu_bar, tearoff=0) file_menu.add_command(label="Open", command=open_file) file_menu.add_command(label="Save", command=save_file) menu_bar.add_cascade(label="File", menu=file_menu) root.config(menu=menu_bar) ``` 4. 添加按钮和编辑操作: ```python cut_button = tk.Button(root, text="Cut", command=text.cut) copy_button = tk.Button(root, text="Copy", command=text.copy) paste_button = tk.Button(root, text="Paste", command=text.paste) cut_button.pack(side=tk.LEFT) copy_button.pack(side=tk.LEFT) paste_button.pack(side=tk.LEFT) ``` 5. 实现打开和保存文件的功能: ```python def open_file(): file_path = filedialog.askopenfilename() with open(file_path, "r") as f: text.insert(tk.END, f.read()) def save_file(): file_path = filedialog.asksaveasfilename() with open(file_path, "w") as f: f.write(text.get("1.0", tk.END)) ``` 6. 运行程序: ```python root.mainloop() ``` 完整代码如下: ```python import tkinter as tk from tkinter import filedialog root = tk.Tk() text = tk.Text(root) text.pack() menu_bar = tk.Menu(root) file_menu = tk.Menu(menu_bar, tearoff=0) file_menu.add_command(label="Open", command=open_file) file_menu.add_command(label="Save", command=save_file) menu_bar.add_cascade(label="File", menu=file_menu) root.config(menu=menu_bar) cut_button = tk.Button(root, text="Cut", command=text.cut) copy_button = tk.Button(root, text="Copy", command=text.copy) paste_button = tk.Button(root, text="Paste", command=text.paste) cut_button.pack(side=tk.LEFT) copy_button.pack(side=tk.LEFT) paste_button.pack(side=tk.LEFT) def open_file(): file_path = filedialog.askopenfilename() with open(file_path, "r") as f: text.insert(tk.END, f.read()) def save_file(): file_path = filedialog.asksaveasfilename() with open(file_path, "w") as f: f.write(text.get("1.0", tk.END)) root.mainloop() ``` 这样一个简单的 Python 微型文本编辑器就完成了。你可以根据需要对其进行扩展,添加更多的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值