1-PyQt5多文档设计概念
PyQt5多文档界面,MDI(Multiple Document Interface)允许用户在同一应用程序窗口中打开和管理多个窗口文档。比较典型的多文档界面就比如我们常用的办公三件套:Word,Excel,PowerPoint等。其中每个文档通常是一个独立的子窗口,可以包含不同的内容,例如文本、图形或其它应用程序数据。
2-PyQt5多文档文本编辑器设计
2.1 Document UI文件设计
新建-widget-拖拽一个文本编辑控件在窗口中,设计好布局即可。
Document其实就是在MainWindow 主窗口运行时的一个个文档,因此,从面向对象的角度设计,该文档应该有自己的一些方法属性,比如:字体颜色、字体大小、文本居中、等。
def get_Text(self):
return self.ui.plainTextEdit.toPlainText()
def textPaste(self):
self.ui.plainTextEdit.paste()
def textSetFont(self):
iniFont=self.ui.plainTextEdit.font()
font,OK=QFontDialog.getFont(iniFont)
if (OK):
self.ui.plainTextEdit.setFont(font)
def toggleBold(self):
cursor = self.ui.plainTextEdit.textCursor()
current_format = cursor.charFormat()
char_format = QTextCharFormat()
char_format.setFontWeight(QFont.Bold if current_format.fontWeight() == QFont.Normal else QFont.Normal)
cursor.mergeCharFormat(char_format)
def toggleItalic(self):
cursor = self.ui.plainTextEdit.textCursor()
current_format = cursor.charFormat()
char_format = QTextCharFormat()
char_format.setFontItalic(not current_format.fontItalic())
cursor.mergeCharFormat(char_format)
def toggleD(self):
cursor = self.ui.plainTextEdit.textCursor()
current_format = cursor.charFormat()
char_format = QTextCharFormat()
char_format.setFontStrikeOut(not current_format.fontStrikeOut())
cursor.mergeCharFormat(char_format)
def toggleUnder(self):
cursor = self.ui.plainTextEdit.textCursor()
current_format = cursor.charFormat()
char_format = QTextCharFormat()
char_format.setFontUnderline(not current_format.fontUnderline())
cursor.mergeCharFormat(char_format)
def toggleCenter(self):
cursor = self.ui.plainTextEdit.textCursor()
current_format = cursor.blockFormat()
block_format = QTextBlockFormat()
block_format.setAlignment(Qt.AlignCenter)
cursor.mergeBlockFormat(block_format)
def toggleLeft(self):
cursor = self.ui.plainTextEdit.textCursor()
current_format = cursor.blockFormat()
block_format = QTextBlockFormat()
block_format.setAlignment(Qt.AlignLeft)
cursor.mergeBlockFormat(block_format)
def toggleRight(self):
cursor = self.ui.plainTextEdit.textCursor()
current_format = cursor.blockFormat()
block_format = QTextBlockFormat()
block_format.setAlignment(Qt.AlignRight)
cursor.mergeBlockFormat(block_format)
def toggleJustify(self):
cursor = self.ui.plainTextEdit.textCursor()
current_format = cursor.blockFormat()
block_format = QTextBlockFormat()
block_format.setAlignment(Qt.AlignJustify)
cursor.mergeBlockFormat(block_format)
def setTextColor(self):
color= QColorDialog.getColor()
if color.isValid():
cursor = self.ui.plainTextEdit.textCursor()
char_format = QTextCharFormat()
char_format.setForeground(color)
cursor.mergeCharFormat(char_format)
def selectAll(self):
self.ui.plainTextEdit.selectAll()
def re_do(self):
self.ui.plainTextEdit.redo()
def un_do(self):
self.ui.plainTextEdit.undo()
def loadFile(self, file_name): ##打开文件
f=codecs.open(file_name,encoding='utf-8')
try:
for line in f: #每次读取一行
self.ui.TextEdit.append(line.strip())
finally:
f.close()
2.2 MainWindow UI文件设计
工具栏,菜单栏实现文件打开、新建、保存、另存为、字体样式等。QAction的相关设计请看前期【PyQt5从入门到精通系列02-布局(数据展示GUI小项目)】。此处,还需放置一个关键的控件:QMdiArea。直接在主窗口工作区拖拽放置,设置布局即可。
QMdiArea常用方法
-
addSubWindow():将给定的 QWidget 添加为子窗口,并返回对应的 QMdiSubWindow 对象。
-
cascadeSubWindows():以级联的方式排列所有子窗口。
-
tileSubWindows():以平铺的方式排列所有子窗口。
-
closeActiveSubWindow():关闭当前活动的子窗口。
-
subWindowList():返回子窗口的列表,可以按照 CreationOrder 或 StackingOrder 的顺序排列。
@pyqtSlot() #新建文档
def on_new_add_action_triggered(self):
#实例化一个Document对象
Doc = QDocument(self)
#将该Document对象添加至MDI
self.ui.mdiArea.addSubWindow(Doc)
Doc.show()
@pyqtSlot()
#打开已经存在的文档
def on_open_file_action_triggered(self):
current_path = os.getcwd() # 获取当前路径
file_name, filter = QFileDialog.getOpenFileName(self, "打开一个文件", curPath,
"文本文件(*.cpp *.h *.py);;所有文件(*.*)")
if (file_name == ""):
return
formDoc = QDocument(self)
self.ui.mdiArea.addSubWindow(formDoc)
formDoc.loadFile(filename)
formDoc.show()
def on_save_as_action_triggered(self):
# 获取当前活跃文档的文本编辑控件
active_subwindow = self.ui.mdiArea.activeSubWindow()
if active_subwindow:
text_edit = active_subwindow.widget()
# 打开文件对话框,获取用户选择的保存路径
document_path, _ = QFileDialog.getSaveFileName(self, 'Save As', '', 'Text Files (*.txt);;All Files (*)')
if document_path:
# 保存文档内容到指定路径
with open(document_path, 'w',encoding="utf-8") as file:
file.write(text_edit.get_Text())
# 将文件路径保存到子窗口的属性中
active_subwindow.setProperty('FilePath', document_path)
# 关闭全部
@pyqtSlot()
def on_action_4_triggered(self):
self.ui.mdiArea.closeAllSubWindows()
@pyqtSlot(bool) #MDI模式
def on_actionMDI_triggered(self, checked):
if checked: # Tab多页显示模式
self.ui.mdiArea.setViewMode(QMdiArea.TabbedView) # Tab多页显示模式
self.ui.mdiArea.setTabsClosable(True) # 页面可关闭
self.ui.action_2.setEnabled(False)
self.ui.action.setEnabled(False)
else: # 子窗口模式
self.ui.mdiArea.setViewMode(QMdiArea.SubWindowView) # 子窗口模式
self.ui.action_2.setEnabled(True)
self.ui.action.setEnabled(True)
@pyqtSlot() #级联展开
def on_action_2_triggered(self):
self.ui.mdiArea.cascadeSubWindows()
@pyqtSlot() #平铺展开
def on_action_triggered(self):
self.ui.mdiArea.tileSubWindows()
@pyqtSlot() #剪切操作-需要在Document.py中实现text_edit的textCut
def on_actEdit_Cut_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.textCut()
@pyqtSlot() #复制文本,同上
def on_copy_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.textCopy()
@pyqtSlot() #Paste操作,同上
def on_paste_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.textPaste()
@pyqtSlot() #字体设置,同上
def on_actEdit_Font_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.textSetFont()
@pyqtSlot()
def on_bold_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.toggleBold()
@pyqtSlot()
def on_Iter_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.toggleItalic()
@pyqtSlot()
def on_delete_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.toggleD()
@pyqtSlot()
def on_under_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.toggleUnder()
@pyqtSlot()
def on_centor_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.toggleCenter()
@pyqtSlot()
def on_left_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.toggleLeft()
@pyqtSlot()
def on_right_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.toggleRight()
@pyqtSlot()
def on_ld_action_triggered(self):
formDoc = self.ui.mdiArea.activeSubWindow().widget()
formDoc.toggleJustify()
def changeTextColor(self):
active_subwindow = self.ui.mdiArea.activeSubWindow()
if active_subwindow:
text_edit = active_subwindow.widget()
text_edit.setTextColor()
def on_select_all_action_triggered(self):
active_subwindow = self.ui.mdiArea.activeSubWindow()
if active_subwindow:
text_edit = active_subwindow.widget()
text_edit.selectAll()
def on_redo_action_triggered(self):
active_subwindow = self.ui.mdiArea.activeSubWindow()
if active_subwindow:
text_edit = active_subwindow.widget()
text_edit.re_do()
def on_recover_action_triggered(self):
active_subwindow = self.ui.mdiArea.activeSubWindow()
if active_subwindow:
text_edit = active_subwindow.widget()
text_edit.un_do()