【Python】使用tkinter设计开发Windows桌面程序记事本(5)

发布时间:2024年01月14日

上一篇:【Python】使用tkinter设计开发Windows桌面程序记事本(4)-CSDN博客

下一篇:待羽翼丰满之时,必将是文章更新之日!

作者发炎

本篇文章继承了前面四篇文章,并且实现了新建、保存、另存、打开、页面设置、退出功能。

现阶段我还不能实现打印功能,而新窗口要在最后阶段完成,所有我选择忽略这两个功能。

近期我将暂停本项目进度更新(能力受限),但博客文章不受影响,会不定期发布。

有疑问或建议,欢迎在评论区戳我哟!

设计步骤

?在"记事本项目" --> "code"目录下新建了一个"记事本功能设计_2.py"文件,开始本阶段的项目设计开发,如下图:

运行结果

导入【记事本项目.code.记事本底座】
导入【记事本项目.code.记事本功能设计_1】
导入【记事本项目.code.记事本_页面设置】
导入【记事本项目.code.记事本_页面设置功能设计_1】
光标位置:行 1 列 1
1editText: ['\n']
2editText: ['\n']
2readText: ['']
    ...
    ...
    ...
光标位置:行 7 列 16
1editText: ['本篇文章实现了新建、保存、另存、打开、页面设置、退出功能\n\n不足的是新窗口和打印功能未实现\n\n但是近期我将暂停本项目的更新,假以时日,羽翼丰满,再更新\n\n欢迎关注我的动态,一起变得更强!\n']
2editText: ['本篇文章实现了新建、保存、另存、打开、页面设置、退出功能\n\n不足的是新窗口和打印功能未实现\n\n但是近期我将暂停本项目的更新,假以时日,羽翼丰满,再更新\n\n欢迎关注我的动态,一起变得更强!\n']
2readText: ['']
光标位置:行 7 列 17

代码示例:记事本功能设计_2.py

"""
    记事本功能设计

不足:
    1.新窗口未完成,因为现在实现的话,会局限这里(功能不完全),所以要在最后实现
    2.打印未实现,能力所限,只好忽略
    3.在点击菜单栏后理应该可以与键盘交互,但未实现,因为Menu()没有鼠标焦点属性

"""

# 通配符 "*"
__all__ = ['Notepad_2']

# 导入内置模块
import tkinter.messagebox as tkmb
import tkinter.filedialog as tkfd

# 导入"记事本功能设计_1"模块
from 记事本项目.code.记事本功能设计_1 import Notepad_1
# 导入"记事本_页面设置功能设计_1"模块
from 记事本项目.code.记事本_页面设置功能设计_1 import PageSetup_1


class Notepad_2(Notepad_1):
    """ 继承Notepad_1, 设计记事本功能 """
    def __init__(self):
        """ 重写父类的构造方法 """
        # 调用父类的构造方法
        super().__init__()

        """ 开始对记事本功能进行设计 """

        self.readText = ''  # 读取编辑区文本数据

        # 新建(N)
        self.fileMenu.entryconfigure(0, command=self.newText)
        """ 新窗口(W)要在最后完成,因为"新窗口"需要完整的功能 """
        # self.fileMenu.entryconfigure(1, command=self.xxx)
        # 打开(O)...
        self.fileMenu.entryconfigure(2, command=self.openFile)
        # 保存(S)
        self.fileMenu.entryconfigure(3, command=self.saveFile)
        # 另存为(A)...
        self.fileMenu.entryconfigure(4, command=self.saveAsFile)
        """ 页面设置(U)...需要单独一个继承类来完成 """
        self.fileMenu.entryconfigure(6, command=self.pageSetup)
        """ 打印(P)... 水平有限,功能未完成 """
        # self.fileMenu.entryconfigure(7, command=self.xxx)
        # 退出
        self.fileMenu.entryconfigure(9, command=self.destroy)

        # 捆绑按键按下编辑文本事件
        self.bind('<KeyPress>', self.editText)
        # 新建文本 键盘触发
        self.bind('<Control-Key-n>', self.newText)
        """ 新窗口未实现 """
        # self.bind('Control-Shift-Key-N>', self.xxx)
        # 打开文件(BUG) 键盘触发
        self.bind('<Control-Key-o>', self.openFile)
        # 保存文件 键盘触发
        self.bind('<Control-Key-s>', self.saveFile)
        # 文件另存为 键盘触发
        self.bind('<Control-Shift-Key-S>', self.saveAsFile)
        """ 打印未实现 """
        # self.bind('Control-Key-p>', self.xxx)


    # 页面设置
    def pageSetup(self, event=None):
        pageSetup_ui = PageSetup_1()    # 实例化"页面设置"UI


    # 文件另存为
    def saveAsFile(self, event=None):
        global openPath
        # 文件保存类型
        filetypes = [("文本文档", ".txt"), ("所有文件", ".*")]
        # 保存文件对话框
        savePath = tkfd.asksaveasfile(defaultextension=".txt", initialfile='*.txt', filetypes=filetypes)
        # 确定保存
        if savePath:
            # 把文本编辑的数据写入文件
            with open(savePath.name, 'w', encoding=savePath.encoding) as file:
                file.write(self.text.get('1.0', 'end')[:-1:])
            # 窗口标题前去掉'*'
            self.title(self.title()[1::])
            # 修改标题
            self.title(f'{savePath.name.split("/")[-1]} - 记事本')
            self.readText = self.text.get('1.0', 'end')[:-1:]
            openPath = savePath


    # 保存文件
    def saveFile(self, event=None):
        global openPath
        # 判断文本是否编辑过
        if self.title()[0] == '*':
            self.bell()  # 警告声
            # 从程序打开进入的编辑
            if not self.readText:
                # 消息对话框选择是否保存
                ifYes = tkmb.askyesnocancel('记事本', f'你想将更改保存到 无标题 吗?')
                # 如果选择是
                if ifYes:
                    # 文件另存为
                    self.saveAsFile()

            # 打开文件后保存
            else:
                # 保存文本数据,写入文件
                with open(openPath.name, 'w', encoding=openPath.encoding) as file:
                    file.write(self.text.get('1.0', 'end')[:-1:])
                # 窗口标题前去掉'*'
                self.title(self.title()[1::])
                self.readText = self.text.get('1.0', 'end')[:-1:]


    # 打开文件
    def openFile(self, keyTrigger=None):
        global openPath
        ifYes = True
        savePath = True
        # 如果是键盘触发(必须)
        if keyTrigger:
            # 键盘Ctrl+O 触发,光标处会加入换行(不知道是否为BUG,求指教)
            self.text.delete('1.0', 'end')
            self.text.insert('1.0', self.textGet[:-1:])

        # 判断文本是否编辑过
        if self.title()[0] == '*':
            self.bell()  # 警告声
            # 从程序打开进入的编辑
            if not self.readText:
                fileName = f'你想将更改保存到 {self.title().split(" ")[0][1::]} 吗?'
            # 从文件打开进入的编辑
            else:
                fileName = f'你想将更改保存到\n{openPath.name}\n吗?'

            # 在消息对话框选择是否保存当前编辑的文本
            ifYes = tkmb.askyesnocancel('记事本', fileName)
            # 确定
            if ifYes:
                # 判断保存的文件是否存在
                if not self.readText:
                    # 文件另存为
                    self.saveAsFile()
                else:
                    # 保存文本数据,写入文件
                    with open(openPath.name, 'w', encoding=openPath.encoding) as file:
                        file.write(self.text.get('1.0', 'end')[:-1:])
                    # 窗口标题前去掉'*'
                    self.title(self.title()[1::])
                    self.readText = self.text.get('1.0', 'end')[:-1:]

        # 打开文件
        if ifYes != None and savePath:
            # 消息对话框打开文件
            # must be -defaultextension, -filetypes, -initialdir, -initialfile, -multiple, -parent, -title, or -typevariable
            filetypes = [('文本文档', '.txt'), ('所有文件', '.*')]
            # 打开文件对话框
            self.openPath = tkfd.askopenfile(filetypes=filetypes)
            # 确定打开文件
            if self.openPath:
                openPath = self.openPath
                # 窗口初始化
                self.text.delete('1.0', 'end')
                self.readText = ''
                # 打开文件读取数据插入到文本域
                with open(self.openPath.name, 'r', encoding=self.openPath.encoding) as file:
                    for i in file:
                        self.text.insert('end', i)
                        # 更新文本读取数据
                        self.readText += i
                # 修改窗口标题
                self.title(f'{self.openPath.name.split("/")[-1]} - 记事本')
                self.event_generate('<Key>')
                # 数据更新


    # 新建文本
    def newText(self, event=None):
        ifYes = True
        savePath = True
        # 判断文本是否编辑过
        if self.title()[0] == '*':
            self.bell()  # 警告声
            # 从程序打开进入的编辑
            if not self.readText:
                fileName = f'你想将更改保存到 {self.title().split(" ")[0][1::]} 吗?'
            # 从文件打开进入的编辑
            else:
                fileName = f'你想将更改保存到\n{openPath.name}\n吗?'

            # 在消息对话框选择是否保存当前编辑的文本
            ifYes = tkmb.askyesnocancel('记事本', fileName)
            # 确定
            if ifYes:
                # 判断保存的文件是否存在
                if not self.readText:
                    # 文件保存类型
                    filetypes = [("文本文档", ".txt"), ("所有文件", ".*")]
                    # 保存文件对话框
                    savePath = tkfd.asksaveasfile(defaultextension=".txt", initialfile='*.txt', filetypes=filetypes)
                    # 确定保存
                    if savePath:
                        # 把文本编辑的数据写入文件
                        with open(savePath.name, 'w', encoding=savePath.encoding) as file:
                            file.write(self.text.get('1.0', 'end')[:-1:])
                else:
                    # 保存文本数据,写入文件
                    with open(openPath.name, 'w', encoding=openPath.encoding) as file:
                        file.write(self.text.get('1.0', 'end')[:-1:])

        # 初始化窗口
        if ifYes != None and savePath:
            self.title('无标题 - 记事本')
            self.readText = ''
            self.text.delete('1.0', 'end')
            self.event_generate('<Key>')


    # 编辑Text文本
    def editText(self, event=None):
        print('1editText:', [self.text.get('1.0', 'end')])
        data = self.text.get('1.0', 'end')
        # 文本编辑时窗口标题前加入'*'
        if data[:-1:] != self.readText and data != '\n' and self.title()[0] != '*':
            self.title('*' + self.title())
        # 编辑过文本未保存或与原文本相同时窗口标题前去掉'*'
        elif data[:-1:] == self.readText or data == '\n':
            if self.title()[0] == '*':
                self.title(self.title()[1::])

        # 如果是键盘Ctrl+O触发打开文件(必须)
        self.textGet = self.text.get('1.0', 'end')

        print('2editText:', [self.text.get('1.0', 'end')])
        print('2readText:', [self.readText])


# 代码测试
if __name__ == '__main__':
    ui = Notepad_2()    # 实例化记事本UI
    ui.mainloop()       # 循环窗口运行
else:
    print(f'导入【{__name__}】')

作者:周华

创作日期:2024/1/13

文章来源:https://blog.csdn.net/zhouhua2022/article/details/135577561
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。