一、效果展示
二、设计PyQt界面
2.1、设置图标
self.setWindowIcon(QIcon('./images/icon/1.png')) # 窗口图标
2.2、设置标题
self.file_name = '无标题-新建文本文档' # 默认文件名
self.setWindowTitle(self.file_name) # 窗口标题
2.3、添加菜单栏、工具栏、状态栏
# 创建菜单栏
self.menu_bar = QMenuBar(self)
self.setMenuBar(self.menu_bar)
# 创建工具栏
self.tool_bar = QToolBar(self)
self.addToolBar(self.tool_bar)
self.tool_bar.addAction(self.new_action) # 添加新建操作到工具栏
self.tool_bar.addAction(self.newS_action) # 添加保存操作到工具栏
# 创建字体和颜色按钮
self.font_btn = QToolButton(self) # 字体按钮
self.font_btn.setIcon(QIcon('./images/icon/font.png')) # 设置图标
self.tool_bar.addWidget(self.font_btn)
self.color_btn = QToolButton(self) # 颜色按钮
self.color_btn.setIcon(QIcon('./images/icon/color.png')) # 设置图标
self.tool_bar.addWidget(self.color_btn)
# 创建文本编辑区
self.text_edit = QTextEdit(self)
self.setCentralWidget(self.text_edit)
2.4、菜单栏中添加菜单
# 创建文件菜单
self.file_menu = QMenu('文件(F)', self)
self.menu_bar.addMenu(self.file_menu)
# 创建编辑菜单
self.edit_menu = QMenu('编辑(E)', self)
self.menu_bar.addMenu(self.edit_menu)
2.5、菜单栏中的菜单添加动作(选项)
# 为文件菜单创建操作
self.new_action = QAction('新建(N)', self) # 新建操作
self.new_action.setIcon(QIcon('./images/icon/new.png')) # 设置图标
self.new_action.setShortcut(QKeySequence.New) # 设置快捷键
self.file_menu.addAction(self.new_action) # 添加到文件菜单
self.newO_action = QAction('打开(O)', self) # 打开操作
self.newO_action.setIcon(QIcon('./images/icon/open.png')) # 设置图标
self.newO_action.setShortcut(QKeySequence.Open) # 设置快捷键
self.file_menu.addAction(self.newO_action)
self.newS_action = QAction('保存(S)', self) # 保存操作
self.newS_action.setIcon(QIcon('./images/icon/save.png')) # 设置图标
self.newS_action.setShortcut(QKeySequence.Save) # 设置快捷键
self.file_menu.addAction(self.newS_action)
self.newA_action = QAction('另保存为(A)', self) # 另存为操作
self.newA_action.setIcon(QIcon('./images/icon/save.png')) # 设置图标
self.newA_action.setShortcut(QKeySequence.SaveAs) # 设置快捷键
self.file_menu.addAction(self.newA_action)
# 为编辑菜单创建操作
self.newC_action = QAction('复制(C)', self) # 复制操作
self.newC_action.setIcon(QIcon('./images/icon/copy.png')) # 设置图标
self.newC_action.setShortcut(QKeySequence.Copy) # 设置快捷键
self.edit_menu.addAction(self.newC_action)
self.newP_action = QAction('粘贴(P)', self) # 粘贴操作
self.newP_action.setIcon(QIcon('./images/icon/paste.png')) # 设置图标
self.newP_action.setShortcut(QKeySequence.Paste) # 设置快捷键
self.edit_menu.addAction(self.newP_action)
self.newT_action = QAction('剪辑(T)', self) # 剪切操作
self.newT_action.setIcon(QIcon('./images/icon/textitalic.png')) # 设置图标
self.newT_action.setShortcut(QKeySequence.Cut) # 设置快捷键
self.edit_menu.addAction(self.newT_action)
self.newU_action = QAction('撤销(U)', self) # 撤销操作
self.newU_action.setIcon(QIcon('./images/icon/undo.png')) # 设置图标
self.newU_action.setShortcut(QKeySequence.Undo) # 设置快捷键
self.edit_menu.addAction(self.newU_action)
self.newR_action = QAction('反撤销(R)', self) # 反撤销操作
self.newR_action.setIcon(QIcon('./images/icon/dir.png')) # 设置图标
self.newR_action.setShortcut(QKeySequence.Redo) # 设置快捷键
self.edit_menu.addAction(self.newR_action)
2.6、添加文本编辑区域
# 创建文本编辑区使其设置中心窗口
self.text_edit = QTextEdit(self)
self.setCentralWidget(self.text_edit)
三、菜单栏业务实现
3.1连接操作与其相应的槽函数
self.new_action.triggered.connect(self.new_action_slot) # 新建文件
self.newO_action.triggered.connect(self.open_action) # 打开文件
self.newS_action.triggered.connect(self.save_action_slot) # 保存文件
self.newA_action.triggered.connect(self.saveAs_action_slot) # 另存为文件
3.2、连接编辑操作
self.newC_action.triggered.connect(self.text_edit.copy) # 复制
self.newP_action.triggered.connect(self.text_edit.paste) # 粘贴
self.newT_action.triggered.connect(self.text_edit.cut) # 剪切
self.newU_action.triggered.connect(self.text_edit.undo) # 撤销
self.newR_action.triggered.connect(self.text_edit.redo) # 反撤销
3.3、新建文件
新建文件这个函数操作的主要逻辑为:
如果当前打开的文件文本内容有被修改:
弹出消息提示框,是否要对更改进行保存
保存:
如果此时的文件名为 无标题-记事本, 要进行另存为
否则:
进行保存 (打开原来的文件,把文本框中的内容写入该文件,文件关闭)
文本区域清空
窗口标题变成了无标题-记事本
不保存:
文本区域清空
窗口标题变成了无标题-记事本
取消:
什么都不做
如果当前打开的文件文本内容没有被修改:
文本区域清空
窗口标题变成了无标题-记事本
def new_action_slot(self):
# 处理新文件操作
rest = self.text_edit.document().isModified() # 检查文档是否被修改
if rest:
btn_res = QMessageBox.question(self, '记事本', '是否保存?',
QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
if btn_res == QMessageBox.Yes:
self.save_action_slot() # 保存文件
self.text_edit.clear() # 清空文本编辑区
self.file_name = '无标题记事本'
self.setWindowTitle(self.file_name) # 更新窗口标题
elif btn_res == QMessageBox.No:
self.text_edit.clear() # 清空文本编辑区
self.file_name = '无标题记事本'
self.setWindowTitle(self.file_name) # 更新窗口标题
else:
self.text_edit.clear() # 清空文本编辑区
self.file_name = '无标题记事本'
self.setWindowTitle(self.file_name) # 更新窗口标题
3.4、打开文件
如果当前这个文本内容没有做任何修改:
弹出一个文件选择对话框,选择一个文件并打开,读这个文件的内容,把读到内容设 置到文本编辑框中,文件本身关闭!
窗口标题变成了打开的这个文件的名字
如果当前这个文本内容有做修改:
弹出消息对话框,询问是否对修改进行保存。
保存:
如果此时窗口标题为 无标题-记事本
进行另存为
否则:
保存
弹出一个文件选择对话框,选择一个文件并打开,读这个文件的内容,把读到内 容设置到文本编辑框中,文件本身关闭!
窗口标题变成了打开的这个文件的名字
不保存:
弹出一个文件选择对话框,选择一个文件并打开,读这个文件的内容,把读到内 容设置到文本编辑框中,文件本身关闭!
窗口标题变成了打开的这个文件的名字
取消:
说明是误触,什么都不做
def open_action(self):
# 处理打开文件操作
rest = self.text_edit.document().isModified()
if rest:
btn_res = QMessageBox.question(self, '记事本', '是否保存?',
QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
if btn_res == QMessageBox.Yes:
self.save_action_slot() # 保存文件
self.open_file() # 打开文件
elif btn_res == QMessageBox.No:
self.open_file() # 打开文件
else:
self.open_file() # 直接打开文件
def open_file(self):
# 打开文件对话框,选择文件进行打开
self.file_path = QFileDialog.getOpenFileName(self, '打开', './', '记事本TXT(*.txt)')[0]
print(self.file_path)
fs = QFile(self.file_path) # 创建QFile对象
fs.open(QFile.ReadOnly) # 以只读方式打开文件
if fs.isOpen():
data = fs.readAll() # 读取文件内容
print(data)
self.text_edit.setText(bytearray(data).decode('utf-8')) # 将内容设置到文本编辑区
self.file_name = QFileInfo(self.file_path).fileName() # 获取文件名
self.setWindowTitle(self.file_name) # 更新窗口标题
fs.close() # 关闭文件
else:
print('文件未打开') # 打开失败的提示
3.5、保存文件
如果当前操作的文件 文件名为 无标题-记事本
进行另存为
否则:
打开当前的这个文件,获取文本框中的内容,写入到文件中,文件关闭!
窗口标题变成了当前打开文件的文件字
修改文本框中的文本状态为 未修改
def save_action_slot(self):
# 保存文件操作
if self.file_name == '无标题':
self.saveAs_action_slot() # 如果没有文件名,则执行另存为
else:
fs = QFile(self.file_path) # 创建QFile对象
fs.open(QFile.WriteOnly) # 以写入方式打开文件
if fs.isOpen():
text = self.text_edit.toPlainText() # 获取文本编辑区中的纯文本
fs.write(text.encode('utf-8')) # 写入文件
self.file_name = QFileInfo(self.file_path).fileName() # 更新文件名
self.setWindowTitle(self.file_name) # 更新窗口标题
fs.close() # 关闭文件
self.text_edit.document().setModified(False) # 重置文档修改状态
else:
print('文件打开失败') # 写入失败的提示
3.6、文件另存为
根据window中记事本的另存为动作,
分析:
弹出一个文件选择对话框,输入新保存的文件名字,保存
打开文件,获取文本框中的内容, 写入文件中, 文件关闭
窗口标题变成新保存文件的名字!
修改文本框中的文本状态为 未修改
def saveAs_action_slot(self):
# 另存为文件操作
self.file_path = QFileDialog.getSaveFileName(self, '另存为', './', '记事本TXT(*.txt)')[0]
fs = QFile(self.file_path) # 创建QFile对象
fs.open(QFile.WriteOnly) # 以写入方式打开文件
if fs.isOpen():
text = self.text_edit.toPlainText() # 获取文本编辑区中的纯文本
fs.write(text.encode('utf-8')) # 写入文件
self.file_name = QFileInfo(self.file_path).fileName() # 更新文件名
self.setWindowTitle(self.file_name) # 更新窗口标题
fs.close() # 关闭文件
self.text_edit.document().setModified(False) # 重置文档修改状态
else:
print('文件另存为失败') # 另存为失败的提示
3.7 、文本的复制、粘贴、剪切、撤销、恢复
在QTextEdit中查找 都有对应的槽函数 copy()、paste()、cut()、undo()、redo()
self.newC_action.triggered.connect(self.text_edit.copy) # 复制
self.newP_action.triggered.connect(self.text_edit.paste) # 粘贴
self.newT_action.triggered.connect(self.text_edit.cut) # 剪切
self.newU_action.triggered.connect(self.text_edit.undo) # 撤销
self.newR_action.triggered.connect(self.text_edit.redo) # 反撤销
3.8、工具栏业务实现
def font_slot(self):
# 字体选择操作
font = QFontDialog.getFont(self)[0] # 弹出字体选择对话框
print(font)
self.text_edit.setCurrentFont(font) # 设置文本编辑区的当前字体
def color_slot(self):
# 颜色选择操作
color = QColorDialog.getColor(QColor(), self) # 弹出颜色选择对话框
self.text_edit.setTextColor(color) # 设置文本编辑区的文本颜色
四、用到的库函数
QMainWinodw
setWindowTitle() 修改窗口标题
setWindowIcon() 设置窗口图标
setMenuBar()
addToolBar()
setStatusBar() 设置菜单栏 添加工具栏 设置状态栏
setCentralWidget() 设置核心区域
QMenuBar 菜单栏
addMenu() 添加菜单
QMenu
setTitle() 设置标题
addAction() 添加动作
QAction
setText() 设置文本
setIcon() 设置图标
setShortCut() 设置快捷按键
triggered() 信号
QToolBar 工具栏
addAction() 添加动作
addWidget() 添加其他控件
QToolButton 工具按钮
setIcon() 设置图标
clicked() 点击信号
QStatusBar 状态栏
QTextEdit
document()文本文档的获取
toPlainText()内容的获取
clear()内容的清空
textChanged()文本修改的内容
setText()设置内容
QTextDocument
isModified()是否有被修改
setModified(bool)修改状态
QMessageBox
question()询问
QFileDialog
getOpenFileName() 获取选择打开的文件完整路径名
getSaveFileName() 获取另存为的文件的完整路径名
QFile
open() 打开文件
isOpened() 是否打开成功
write() 写数据
readAll() 读数据
close() 关闭文件
QFileInfo
fileName() 获取文件名
五、完整代码
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QMenuBar, \
QMenu, QAction, QToolBar, QToolButton, QTextEdit, \
QMessageBox, QFileDialog, QFontDialog, QColorDialog
from PyQt5.QtGui import QIcon, QKeySequence, QColor
from PyQt5.QtCore import QFile, QFileInfo
class My_QMW(QMainWindow):
def __init__(self):
super().__init__()
self.file_name = '无标题-新建文本文档' # 默认文件名
self.file_path = '' # 当前文件路径
self.ui_init() # 初始化UI组件
self.solt_init() # 初始化信号与槽的连接
def ui_init(self):
# 设置主窗口的基本属性
self.setGeometry(700, 300, 1200, 800) # 窗口位置和大小
self.setWindowTitle(self.file_name) # 窗口标题
self.setWindowIcon(QIcon('./images/icon/1.png')) # 窗口图标
# 创建菜单栏
self.menu_bar = QMenuBar(self)
self.setMenuBar(self.menu_bar)
# 创建文件菜单
self.file_menu = QMenu('文件(F)', self)
self.menu_bar.addMenu(self.file_menu)
# 创建编辑菜单
self.edit_menu = QMenu('编辑(E)', self)
self.menu_bar.addMenu(self.edit_menu)
# 为文件菜单创建操作
self.new_action = QAction('新建(N)', self) # 新建操作
self.new_action.setIcon(QIcon('./images/icon/new.png')) # 设置图标
self.new_action.setShortcut(QKeySequence.New) # 设置快捷键
self.file_menu.addAction(self.new_action) # 添加到文件菜单
self.newO_action = QAction('打开(O)', self) # 打开操作
self.newO_action.setIcon(QIcon('./images/icon/open.png')) # 设置图标
self.newO_action.setShortcut(QKeySequence.Open) # 设置快捷键
self.file_menu.addAction(self.newO_action)
self.newS_action = QAction('保存(S)', self) # 保存操作
self.newS_action.setIcon(QIcon('./images/icon/save.png')) # 设置图标
self.newS_action.setShortcut(QKeySequence.Save) # 设置快捷键
self.file_menu.addAction(self.newS_action)
self.newA_action = QAction('另保存为(A)', self) # 另存为操作
self.newA_action.setIcon(QIcon('./images/icon/save.png')) # 设置图标
self.newA_action.setShortcut(QKeySequence.SaveAs) # 设置快捷键
self.file_menu.addAction(self.newA_action)
# 为编辑菜单创建操作
self.newC_action = QAction('复制(C)', self) # 复制操作
self.newC_action.setIcon(QIcon('./images/icon/copy.png')) # 设置图标
self.newC_action.setShortcut(QKeySequence.Copy) # 设置快捷键
self.edit_menu.addAction(self.newC_action)
self.newP_action = QAction('粘贴(P)', self) # 粘贴操作
self.newP_action.setIcon(QIcon('./images/icon/paste.png')) # 设置图标
self.newP_action.setShortcut(QKeySequence.Paste) # 设置快捷键
self.edit_menu.addAction(self.newP_action)
self.newT_action = QAction('剪辑(T)', self) # 剪切操作
self.newT_action.setIcon(QIcon('./images/icon/textitalic.png')) # 设置图标
self.newT_action.setShortcut(QKeySequence.Cut) # 设置快捷键
self.edit_menu.addAction(self.newT_action)
self.newU_action = QAction('撤销(U)', self) # 撤销操作
self.newU_action.setIcon(QIcon('./images/icon/undo.png')) # 设置图标
self.newU_action.setShortcut(QKeySequence.Undo) # 设置快捷键
self.edit_menu.addAction(self.newU_action)
self.newR_action = QAction('反撤销(R)', self) # 反撤销操作
self.newR_action.setIcon(QIcon('./images/icon/dir.png')) # 设置图标
self.newR_action.setShortcut(QKeySequence.Redo) # 设置快捷键
self.edit_menu.addAction(self.newR_action)
# 创建工具栏并添加操作
self.tool_bar = QToolBar(self)
self.addToolBar(self.tool_bar)
self.tool_bar.addAction(self.new_action) # 添加新建操作到工具栏
self.tool_bar.addAction(self.newS_action) # 添加保存操作到工具栏
# 创建字体和颜色按钮
self.font_btn = QToolButton(self) # 字体按钮
self.font_btn.setIcon(QIcon('./images/icon/font.png')) # 设置图标
self.tool_bar.addWidget(self.font_btn)
self.color_btn = QToolButton(self) # 颜色按钮
self.color_btn.setIcon(QIcon('./images/icon/color.png')) # 设置图标
self.tool_bar.addWidget(self.color_btn)
# 创建文本编辑区
self.text_edit = QTextEdit(self)
self.setCentralWidget(self.text_edit)
def solt_init(self):
# 连接操作与其相应的槽函数
self.new_action.triggered.connect(self.new_action_slot) # 新建文件
self.newO_action.triggered.connect(self.open_action) # 打开文件
self.newS_action.triggered.connect(self.save_action_slot) # 保存文件
self.newA_action.triggered.connect(self.saveAs_action_slot) # 另存为文件
# 连接编辑操作
self.newC_action.triggered.connect(self.text_edit.copy) # 复制
self.newP_action.triggered.connect(self.text_edit.paste) # 粘贴
self.newT_action.triggered.connect(self.text_edit.cut) # 剪切
self.newU_action.triggered.connect(self.text_edit.undo) # 撤销
self.newR_action.triggered.connect(self.text_edit.redo) # 反撤销
self.font_btn.clicked.connect(self.font_slot) # 字体按钮点击
self.color_btn.clicked.connect(self.color_slot) # 颜色按钮点击
# 当文本更改时更新窗口标题
self.text_edit.textChanged.connect(self.update_title)
def new_action_slot(self):
# 处理新文件操作
rest = self.text_edit.document().isModified() # 检查文档是否被修改
if rest:
btn_res = QMessageBox.question(self, '记事本', '是否保存?', QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
if btn_res == QMessageBox.Yes:
self.save_action_slot() # 保存文件
self.text_edit.clear() # 清空文本编辑区
self.file_name = '无标题记事本'
self.setWindowTitle(self.file_name) # 更新窗口标题
elif btn_res == QMessageBox.No:
self.text_edit.clear() # 清空文本编辑区
self.file_name = '无标题记事本'
self.setWindowTitle(self.file_name) # 更新窗口标题
else:
self.text_edit.clear() # 清空文本编辑区
self.file_name = '无标题记事本'
self.setWindowTitle(self.file_name) # 更新窗口标题
def open_action(self):
# 处理打开文件操作
rest = self.text_edit.document().isModified()
if rest:
btn_res = QMessageBox.question(self, '记事本', '是否保存?', QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
if btn_res == QMessageBox.Yes:
self.save_action_slot() # 保存文件
self.open_file() # 打开文件
elif btn_res == QMessageBox.No:
self.open_file() # 打开文件
else:
self.open_file() # 直接打开文件
def open_file(self):
# 打开文件对话框,选择文件进行打开
self.file_path = QFileDialog.getOpenFileName(self, '打开', './', '记事本TXT(*.txt)')[0]
print(self.file_path)
fs = QFile(self.file_path) # 创建QFile对象
fs.open(QFile.ReadOnly) # 以只读方式打开文件
if fs.isOpen():
data = fs.readAll() # 读取文件内容
print(data)
self.text_edit.setText(bytearray(data).decode('utf-8')) # 将内容设置到文本编辑区
self.file_name = QFileInfo(self.file_path).fileName() # 获取文件名
self.setWindowTitle(self.file_name) # 更新窗口标题
fs.close() # 关闭文件
else:
print('文件未打开') # 打开失败的提示
def save_action_slot(self):
# 保存文件操作
if self.file_name == '无标题':
self.saveAs_action_slot() # 如果没有文件名,则执行另存为
else:
fs = QFile(self.file_path) # 创建QFile对象
fs.open(QFile.WriteOnly) # 以写入方式打开文件
if fs.isOpen():
text = self.text_edit.toPlainText() # 获取文本编辑区中的纯文本
fs.write(text.encode('utf-8')) # 写入文件
self.file_name = QFileInfo(self.file_path).fileName() # 更新文件名
self.setWindowTitle(self.file_name) # 更新窗口标题
fs.close() # 关闭文件
self.text_edit.document().setModified(False) # 重置文档修改状态
else:
print('文件打开失败') # 写入失败的提示
def saveAs_action_slot(self):
# 另存为文件操作
self.file_path = QFileDialog.getSaveFileName(self, '另存为', './', '记事本TXT(*.txt)')[0]
fs = QFile(self.file_path) # 创建QFile对象
fs.open(QFile.WriteOnly) # 以写入方式打开文件
if fs.isOpen():
text = self.text_edit.toPlainText() # 获取文本编辑区中的纯文本
fs.write(text.encode('utf-8')) # 写入文件
self.file_name = QFileInfo(self.file_path).fileName() # 更新文件名
self.setWindowTitle(self.file_name) # 更新窗口标题
fs.close() # 关闭文件
self.text_edit.document().setModified(False) # 重置文档修改状态
else:
print('文件另存为失败') # 另存为失败的提示
def font_slot(self):
# 字体选择操作
font = QFontDialog.getFont(self)[0] # 弹出字体选择对话框
print(font)
self.text_edit.setCurrentFont(font) # 设置文本编辑区的当前字体
def color_slot(self):
# 颜色选择操作
color = QColorDialog.getColor(QColor(), self) # 弹出颜色选择对话框
self.text_edit.setTextColor(color) # 设置文本编辑区的文本颜色
def update_title(self):
# 文本更改时更新窗口标题
self.setWindowTitle('*' + self.file_name) # 在标题前添加*表示文档被修改过
if __name__ == '__main__':
app = QApplication(sys.argv) # 创建应用程序
windows = My_QMW() # 创建主窗口实例
windows.show() # 显示主窗口
sys.exit(app.exec_()) # 运行主循环