当前位置:   article > 正文

Python: pyqt5 自己写一个窗口文本编辑器_python pyqt5 富文本编辑器

python pyqt5 富文本编辑器

PyQt5是Digia的一套Qt5应用框架与python的结合,同时支持2.x和3.x。Qt库由Riverbank Computing开发,是最强大的GUI库之一。

>>> 今天,我们将尝试用pyqt5写一个文本编辑器。

效果如图:

 支持以下功能:复制、剪切、粘帖、保存、全选、读取、撤回、前进、加粗、斜体、下划线、字体、字号、左中右对齐、打印。

>>> Tips:完整代码在本页最后~


一、安装模块

使用pip安装pyqt5:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyqt5

二、导入模块

导入所需模块:

  1. from PyQt5.QtGui import *
  2. from PyQt5.QtWidgets import *
  3. from PyQt5.QtCore import *
  4. from PyQt5.QtPrintSupport import *
  5. import os
  6. import sys
  7. import uuid
'
运行

三、初始化定义

首先,我们先初始化定义一些后文所需函数。这里如果有看不懂,看到后文就可以理解了。

  1. FONT_SIZES = [7, 8, 9, 10, 11, 12, 13, 14, 18, 24, 36, 48, 64, 72, 96, 144, 288]
  2. IMAGE_EXTENSIONS = ['.jpg','.png','.bmp']
  3. HTML_EXTENSIONS = ['.htm', '.html']
  4. def hexuuid():
  5. return uuid.uuid4().hex
  6. def splitext(p):
  7. return os.path.splitext(p)[1].lower()
  8. class TextEdit(QTextEdit):
  9. def canInsertFromMimeData(self, source):
  10. if source.hasImage():
  11. return True
  12. else:
  13. return super(TextEdit, self).canInsertFromMimeData(source)
  14. def insertFromMimeData(self, source):
  15. cursor = self.textCursor()
  16. document = self.document()
  17. if source.hasUrls():
  18. for u in source.urls():
  19. file_ext = splitext(str(u.toLocalFile()))
  20. if u.isLocalFile() and file_ext in IMAGE_EXTENSIONS:
  21. image = QImage(u.toLocalFile())
  22. document.addResource(QTextDocument.ImageResource, u, image)
  23. cursor.insertImage(u.toLocalFile())
  24. else:
  25. break
  26. else:
  27. return
  28. elif source.hasImage():
  29. image = source.imageData()
  30. uuid = hexuuid()
  31. document.addResource(QTextDocument.ImageResource, uuid, image)
  32. cursor.insertImage(uuid)
  33. return
  34. super(TextEdit, self).insertFromMimeData(source)

四、设置主窗口

开始使用pyqt5,建立一个主窗口,添加按钮等元素位置。

  1. class MainWindow(QMainWindow):
  2. def __init__(self, *args, **kwargs):
  3. super(MainWindow, self).__init__(*args, **kwargs)
  4. layout = QVBoxLayout()
  5. self.editor = TextEdit()
  6. self.editor.setAutoFormatting(QTextEdit.AutoAll)
  7. self.editor.selectionChanged.connect(self.update_format)
  8. font = QFont('Times', 12)
  9. self.editor.setFont(font)
  10. self.editor.setFontPointSize(12)
  11. self.path = None
  12. layout.addWidget(self.editor)
  13. container = QWidget()
  14. container.setLayout(layout)
  15. self.setCentralWidget(container)
  16. self.status = QStatusBar()
  17. self.setStatusBar(self.status)
  18. file_toolbar = QToolBar("文件")
  19. file_toolbar.setIconSize(QSize(14, 14))
  20. self.addToolBar(file_toolbar)
  21. file_menu = self.menuBar().addMenu("&文件")
  22. open_file_action = QAction(QIcon(os.path.join('images', 'blue-folder-open-document.png')), "打开文件", self)
  23. open_file_action.setStatusTip("从本地磁盘中读取文件..")
  24. open_file_action.triggered.connect(self.file_open)
  25. file_menu.addAction(open_file_action)
  26. file_toolbar.addAction(open_file_action)
  27. save_file_action = QAction(QIcon(os.path.join('images', 'disk.png')), "保存", self)
  28. save_file_action.setStatusTip("保存到本地磁盘..")
  29. save_file_action.triggered.connect(self.file_save)
  30. file_menu.addAction(save_file_action)
  31. file_toolbar.addAction(save_file_action)
  32. saveas_file_action = QAction(QIcon(os.path.join('images', 'disk--pencil.png')), "另存为", self)
  33. saveas_file_action.setStatusTip("另存为文件..")
  34. saveas_file_action.triggered.connect(self.file_saveas)
  35. file_menu.addAction(saveas_file_action)
  36. file_toolbar.addAction(saveas_file_action)
  37. print_action = QAction(QIcon(os.path.join('images', 'printer.png')), "打印", self)
  38. print_action.setStatusTip("打印本页..")
  39. print_action.triggered.connect(self.file_print)
  40. file_menu.addAction(print_action)
  41. file_toolbar.addAction(print_action)
  42. edit_toolbar = QToolBar("编辑")
  43. edit_toolbar.setIconSize(QSize(16, 16))
  44. self.addToolBar(edit_toolbar)
  45. edit_menu = self.menuBar().addMenu("&编辑")
  46. undo_action = QAction(QIcon(os.path.join('images', 'arrow-curve-180-left.png')), "撤回", self)
  47. undo_action.setStatusTip("撤回上一个操作..")
  48. undo_action.triggered.connect(self.editor.undo)
  49. edit_menu.addAction(undo_action)
  50. redo_action = QAction(QIcon(os.path.join('images', 'arrow-curve.png')), "重做", self)
  51. redo_action.setStatusTip("重做撤回的操作..")
  52. redo_action.triggered.connect(self.editor.redo)
  53. edit_toolbar.addAction(redo_action)
  54. edit_menu.addAction(redo_action)
  55. edit_menu.addSeparator()
  56. cut_action = QAction(QIcon(os.path.join('images', 'scissors.png')), "剪切", self)
  57. cut_action.setStatusTip("剪切选定内容..")
  58. cut_action.setShortcut(QKeySequence.Cut)
  59. cut_action.triggered.connect(self.editor.cut)
  60. edit_toolbar.addAction(cut_action)
  61. edit_menu.addAction(cut_action)
  62. copy_action = QAction(QIcon(os.path.join('images', 'document-copy.png')), "复制", self)
  63. copy_action.setStatusTip("复制选定内容..")
  64. cut_action.setShortcut(QKeySequence.Copy)
  65. copy_action.triggered.connect(self.editor.copy)
  66. edit_toolbar.addAction(copy_action)
  67. edit_menu.addAction(copy_action)
  68. paste_action = QAction(QIcon(os.path.join('images', 'clipboard-paste-document-text.png')), "粘帖", self)
  69. paste_action.setStatusTip("从剪贴板粘帖..")
  70. cut_action.setShortcut(QKeySequence.Paste)
  71. paste_action.triggered.connect(self.editor.paste)
  72. edit_toolbar.addAction(paste_action)
  73. edit_menu.addAction(paste_action)
  74. select_action = QAction(QIcon(os.path.join('images', 'selection-input.png')), "全选", self)
  75. select_action.setStatusTip("全选所有文字..")
  76. cut_action.setShortcut(QKeySequence.SelectAll)
  77. select_action.triggered.connect(self.editor.selectAll)
  78. edit_menu.addAction(select_action)
  79. edit_menu.addSeparator()
  80. wrap_action = QAction(QIcon(os.path.join('images', 'arrow-continue.png')), "自动换行", self)
  81. wrap_action.setStatusTip("当文字长度超过边框大小时自动换行..")
  82. wrap_action.setCheckable(True)
  83. wrap_action.setChecked(True)
  84. wrap_action.triggered.connect(self.edit_toggle_wrap)
  85. edit_menu.addAction(wrap_action)
  86. format_toolbar = QToolBar("格式")
  87. format_toolbar.setIconSize(QSize(16, 16))
  88. self.addToolBar(format_toolbar)
  89. format_menu = self.menuBar().addMenu("&格式")
  90. self.fonts = QFontComboBox()
  91. self.fonts.currentFontChanged.connect(self.editor.setCurrentFont)
  92. format_toolbar.addWidget(self.fonts)
  93. self.fontsize = QComboBox()
  94. self.fontsize.addItems([str(s) for s in FONT_SIZES])
  95. self.fontsize.currentIndexChanged[str].connect(lambda s: self.editor.setFontPointSize(float(s)) )
  96. format_toolbar.addWidget(self.fontsize)
  97. self.bold_action = QAction(QIcon(os.path.join('images', 'edit-bold.png')), "加粗", self)
  98. self.bold_action.setStatusTip("加粗选定内容..")
  99. self.bold_action.setShortcut(QKeySequence.Bold)
  100. self.bold_action.setCheckable(True)
  101. self.bold_action.toggled.connect(lambda x: self.editor.setFontWeight(QFont.Bold if x else QFont.Normal))
  102. format_toolbar.addAction(self.bold_action)
  103. format_menu.addAction(self.bold_action)
  104. self.italic_action = QAction(QIcon(os.path.join('images', 'edit-italic.png')), "斜体", self)
  105. self.italic_action.setStatusTip("将选定内容设为斜体..")
  106. self.italic_action.setShortcut(QKeySequence.Italic)
  107. self.italic_action.setCheckable(True)
  108. self.italic_action.toggled.connect(self.editor.setFontItalic)
  109. format_toolbar.addAction(self.italic_action)
  110. format_menu.addAction(self.italic_action)
  111. self.underline_action = QAction(QIcon(os.path.join('images', 'edit-underline.png')), "下划线", self)
  112. self.underline_action.setStatusTip("将选定内容加下划线..")
  113. self.underline_action.setShortcut(QKeySequence.Underline)
  114. self.underline_action.setCheckable(True)
  115. self.underline_action.toggled.connect(self.editor.setFontUnderline)
  116. format_toolbar.addAction(self.underline_action)
  117. format_menu.addAction(self.underline_action)
  118. format_menu.addSeparator()
  119. self.alignl_action = QAction(QIcon(os.path.join('images', 'edit-alignment.png')), "靠左对齐", self)
  120. self.alignl_action.setStatusTip("将文本靠左对齐..")
  121. self.alignl_action.setCheckable(True)
  122. self.alignl_action.triggered.connect(lambda: self.editor.setAlignment(Qt.AlignLeft))
  123. format_toolbar.addAction(self.alignl_action)
  124. format_menu.addAction(self.alignl_action)
  125. self.alignc_action = QAction(QIcon(os.path.join('images', 'edit-alignment-center.png')), "居中对齐", self)
  126. self.alignc_action.setStatusTip("将文本居中对齐..")
  127. self.alignc_action.setCheckable(True)
  128. self.alignc_action.triggered.connect(lambda: self.editor.setAlignment(Qt.AlignCenter))
  129. format_toolbar.addAction(self.alignc_action)
  130. format_menu.addAction(self.alignc_action)
  131. self.alignr_action = QAction(QIcon(os.path.join('images', 'edit-alignment-right.png')), "靠右对齐", self)
  132. self.alignr_action.setStatusTip("将文本靠右对齐..")
  133. self.alignr_action.setCheckable(True)
  134. self.alignr_action.triggered.connect(lambda: self.editor.setAlignment(Qt.AlignRight))
  135. format_toolbar.addAction(self.alignr_action)
  136. format_menu.addAction(self.alignr_action)
  137. self.alignj_action = QAction(QIcon(os.path.join('images', 'edit-alignment-justify.png')), "对齐", self)
  138. self.alignj_action.setStatusTip("分散对齐文本..")
  139. self.alignj_action.setCheckable(True)
  140. self.alignj_action.triggered.connect(lambda: self.editor.setAlignment(Qt.AlignJustify))
  141. format_toolbar.addAction(self.alignj_action)
  142. format_menu.addAction(self.alignj_action)
  143. format_group = QActionGroup(self)
  144. format_group.setExclusive(True)
  145. format_group.addAction(self.alignl_action)
  146. format_group.addAction(self.alignc_action)
  147. format_group.addAction(self.alignr_action)
  148. format_group.addAction(self.alignj_action)
  149. format_menu.addSeparator()
  150. self._format_actions = [
  151. self.fonts,
  152. self.fontsize,
  153. self.bold_action,
  154. self.italic_action,
  155. self.underline_action]
  156. self.update_format()
  157. self.update_title()
  158. self.show()

五、定义功能

也是在window的class里,我们定义保存等等的功能

  1. def block_signals(self, objects, b):
  2. for o in objects:
  3. o.blockSignals(b)
  4. def update_format(self):
  5. self.block_signals(self._format_actions, True)
  6. self.fonts.setCurrentFont(self.editor.currentFont())
  7. self.fontsize.setCurrentText(str(int(self.editor.fontPointSize())))
  8. self.italic_action.setChecked(self.editor.fontItalic())
  9. self.underline_action.setChecked(self.editor.fontUnderline())
  10. self.bold_action.setChecked(self.editor.fontWeight() == QFont.Bold)
  11. self.alignl_action.setChecked(self.editor.alignment() == Qt.AlignLeft)
  12. self.alignc_action.setChecked(self.editor.alignment() == Qt.AlignCenter)
  13. self.alignr_action.setChecked(self.editor.alignment() == Qt.AlignRight)
  14. self.alignj_action.setChecked(self.editor.alignment() == Qt.AlignJustify)
  15. self.block_signals(self._format_actions, False)
  16. def dialog_critical(self, s):
  17. dlg = QMessageBox(self)
  18. dlg.setText(s)
  19. dlg.setIcon(QMessageBox.Critical)
  20. dlg.show()
  21. def file_open(self):
  22. path, _ = QFileDialog.getOpenFileName(self, "Open file", "", "HTML documents (*.html);Text documents (*.txt);All files (*.*)")
  23. try:
  24. with open(path, 'rU') as f:
  25. text = f.read()
  26. except Exception as e:
  27. self.dialog_critical(str(e))
  28. else:
  29. self.path = path
  30. self.editor.setText(text)
  31. self.update_title()
  32. def file_save(self):
  33. if self.path is None:
  34. return self.file_saveas()
  35. text = self.editor.toHtml() if splitext(self.path) in HTML_EXTENSIONS else self.editor.toPlainText()
  36. try:
  37. with open(self.path, 'w') as f:
  38. f.write(text)
  39. except Exception as e:
  40. self.dialog_critical(str(e))
  41. def file_saveas(self):
  42. path, _ = QFileDialog.getSaveFileName(self, "Save file", "", "HTML documents (*.html);Text documents (*.txt);All files (*.*)")
  43. if not path:
  44. return
  45. text = self.editor.toHtml() if splitext(path) in HTML_EXTENSIONS else self.editor.toPlainText()
  46. try:
  47. with open(path, 'w') as f:
  48. f.write(text)
  49. except Exception as e:
  50. self.dialog_critical(str(e))
  51. else:
  52. self.path = path
  53. self.update_title()
  54. def file_print(self):
  55. dlg = QPrintDialog()
  56. if dlg.exec_():
  57. self.editor.print_(dlg.printer())
  58. def update_title(self):
  59. self.setWindowTitle("%s - 轩氏记事本 XuanNotepad" % (os.path.basename(self.path) if self.path else "Untitled"))
  60. def edit_toggle_wrap(self):
  61. self.editor.setLineWrapMode( 1 if self.editor.lineWrapMode() == 0 else 0 )

六、生成窗口

最后一步,生成窗口(这里的applicationname你可以改掉):

  1. if __name__ == '__main__':
  2. app = QApplication(sys.argv)
  3. app.setApplicationName("轩氏记事本 XuanNotepad")
  4. window = MainWindow()
  5. window.resize(1300,750)
  6. app.exec_()

七、最终效果

运行程序,我们来看一下效果如何!

 

 


完整代码

最后送上完整代码:

  1. from PyQt5.QtGui import *
  2. from PyQt5.QtWidgets import *
  3. from PyQt5.QtCore import *
  4. from PyQt5.QtPrintSupport import *
  5. import os
  6. import sys
  7. import uuid
  8. FONT_SIZES = [7, 8, 9, 10, 11, 12, 13, 14, 18, 24, 36, 48, 64, 72, 96, 144, 288]
  9. IMAGE_EXTENSIONS = ['.jpg','.png','.bmp']
  10. HTML_EXTENSIONS = ['.htm', '.html']
  11. def hexuuid():
  12. return uuid.uuid4().hex
  13. def splitext(p):
  14. return os.path.splitext(p)[1].lower()
  15. class TextEdit(QTextEdit):
  16. def canInsertFromMimeData(self, source):
  17. if source.hasImage():
  18. return True
  19. else:
  20. return super(TextEdit, self).canInsertFromMimeData(source)
  21. def insertFromMimeData(self, source):
  22. cursor = self.textCursor()
  23. document = self.document()
  24. if source.hasUrls():
  25. for u in source.urls():
  26. file_ext = splitext(str(u.toLocalFile()))
  27. if u.isLocalFile() and file_ext in IMAGE_EXTENSIONS:
  28. image = QImage(u.toLocalFile())
  29. document.addResource(QTextDocument.ImageResource, u, image)
  30. cursor.insertImage(u.toLocalFile())
  31. else:
  32. break
  33. else:
  34. return
  35. elif source.hasImage():
  36. image = source.imageData()
  37. uuid = hexuuid()
  38. document.addResource(QTextDocument.ImageResource, uuid, image)
  39. cursor.insertImage(uuid)
  40. return
  41. super(TextEdit, self).insertFromMimeData(source)
  42. class MainWindow(QMainWindow):
  43. def __init__(self, *args, **kwargs):
  44. super(MainWindow, self).__init__(*args, **kwargs)
  45. layout = QVBoxLayout()
  46. self.editor = TextEdit()
  47. self.editor.setAutoFormatting(QTextEdit.AutoAll)
  48. self.editor.selectionChanged.connect(self.update_format)
  49. font = QFont('Times', 12)
  50. self.editor.setFont(font)
  51. self.editor.setFontPointSize(12)
  52. self.path = None
  53. layout.addWidget(self.editor)
  54. container = QWidget()
  55. container.setLayout(layout)
  56. self.setCentralWidget(container)
  57. self.status = QStatusBar()
  58. self.setStatusBar(self.status)
  59. file_toolbar = QToolBar("文件")
  60. file_toolbar.setIconSize(QSize(14, 14))
  61. self.addToolBar(file_toolbar)
  62. file_menu = self.menuBar().addMenu("&文件")
  63. open_file_action = QAction(QIcon(os.path.join('images', 'blue-folder-open-document.png')), "打开文件", self)
  64. open_file_action.setStatusTip("从本地磁盘中读取文件..")
  65. open_file_action.triggered.connect(self.file_open)
  66. file_menu.addAction(open_file_action)
  67. file_toolbar.addAction(open_file_action)
  68. save_file_action = QAction(QIcon(os.path.join('images', 'disk.png')), "保存", self)
  69. save_file_action.setStatusTip("保存到本地磁盘..")
  70. save_file_action.triggered.connect(self.file_save)
  71. file_menu.addAction(save_file_action)
  72. file_toolbar.addAction(save_file_action)
  73. saveas_file_action = QAction(QIcon(os.path.join('images', 'disk--pencil.png')), "另存为", self)
  74. saveas_file_action.setStatusTip("另存为文件..")
  75. saveas_file_action.triggered.connect(self.file_saveas)
  76. file_menu.addAction(saveas_file_action)
  77. file_toolbar.addAction(saveas_file_action)
  78. print_action = QAction(QIcon(os.path.join('images', 'printer.png')), "打印", self)
  79. print_action.setStatusTip("打印本页..")
  80. print_action.triggered.connect(self.file_print)
  81. file_menu.addAction(print_action)
  82. file_toolbar.addAction(print_action)
  83. edit_toolbar = QToolBar("编辑")
  84. edit_toolbar.setIconSize(QSize(16, 16))
  85. self.addToolBar(edit_toolbar)
  86. edit_menu = self.menuBar().addMenu("&编辑")
  87. undo_action = QAction(QIcon(os.path.join('images', 'arrow-curve-180-left.png')), "撤回", self)
  88. undo_action.setStatusTip("撤回上一个操作..")
  89. undo_action.triggered.connect(self.editor.undo)
  90. edit_menu.addAction(undo_action)
  91. redo_action = QAction(QIcon(os.path.join('images', 'arrow-curve.png')), "重做", self)
  92. redo_action.setStatusTip("重做撤回的操作..")
  93. redo_action.triggered.connect(self.editor.redo)
  94. edit_toolbar.addAction(redo_action)
  95. edit_menu.addAction(redo_action)
  96. edit_menu.addSeparator()
  97. cut_action = QAction(QIcon(os.path.join('images', 'scissors.png')), "剪切", self)
  98. cut_action.setStatusTip("剪切选定内容..")
  99. cut_action.setShortcut(QKeySequence.Cut)
  100. cut_action.triggered.connect(self.editor.cut)
  101. edit_toolbar.addAction(cut_action)
  102. edit_menu.addAction(cut_action)
  103. copy_action = QAction(QIcon(os.path.join('images', 'document-copy.png')), "复制", self)
  104. copy_action.setStatusTip("复制选定内容..")
  105. cut_action.setShortcut(QKeySequence.Copy)
  106. copy_action.triggered.connect(self.editor.copy)
  107. edit_toolbar.addAction(copy_action)
  108. edit_menu.addAction(copy_action)
  109. paste_action = QAction(QIcon(os.path.join('images', 'clipboard-paste-document-text.png')), "粘帖", self)
  110. paste_action.setStatusTip("从剪贴板粘帖..")
  111. cut_action.setShortcut(QKeySequence.Paste)
  112. paste_action.triggered.connect(self.editor.paste)
  113. edit_toolbar.addAction(paste_action)
  114. edit_menu.addAction(paste_action)
  115. select_action = QAction(QIcon(os.path.join('images', 'selection-input.png')), "全选", self)
  116. select_action.setStatusTip("全选所有文字..")
  117. cut_action.setShortcut(QKeySequence.SelectAll)
  118. select_action.triggered.connect(self.editor.selectAll)
  119. edit_menu.addAction(select_action)
  120. edit_menu.addSeparator()
  121. wrap_action = QAction(QIcon(os.path.join('images', 'arrow-continue.png')), "自动换行", self)
  122. wrap_action.setStatusTip("当文字长度超过边框大小时自动换行..")
  123. wrap_action.setCheckable(True)
  124. wrap_action.setChecked(True)
  125. wrap_action.triggered.connect(self.edit_toggle_wrap)
  126. edit_menu.addAction(wrap_action)
  127. format_toolbar = QToolBar("格式")
  128. format_toolbar.setIconSize(QSize(16, 16))
  129. self.addToolBar(format_toolbar)
  130. format_menu = self.menuBar().addMenu("&格式")
  131. self.fonts = QFontComboBox()
  132. self.fonts.currentFontChanged.connect(self.editor.setCurrentFont)
  133. format_toolbar.addWidget(self.fonts)
  134. self.fontsize = QComboBox()
  135. self.fontsize.addItems([str(s) for s in FONT_SIZES])
  136. self.fontsize.currentIndexChanged[str].connect(lambda s: self.editor.setFontPointSize(float(s)) )
  137. format_toolbar.addWidget(self.fontsize)
  138. self.bold_action = QAction(QIcon(os.path.join('images', 'edit-bold.png')), "加粗", self)
  139. self.bold_action.setStatusTip("加粗选定内容..")
  140. self.bold_action.setShortcut(QKeySequence.Bold)
  141. self.bold_action.setCheckable(True)
  142. self.bold_action.toggled.connect(lambda x: self.editor.setFontWeight(QFont.Bold if x else QFont.Normal))
  143. format_toolbar.addAction(self.bold_action)
  144. format_menu.addAction(self.bold_action)
  145. self.italic_action = QAction(QIcon(os.path.join('images', 'edit-italic.png')), "斜体", self)
  146. self.italic_action.setStatusTip("将选定内容设为斜体..")
  147. self.italic_action.setShortcut(QKeySequence.Italic)
  148. self.italic_action.setCheckable(True)
  149. self.italic_action.toggled.connect(self.editor.setFontItalic)
  150. format_toolbar.addAction(self.italic_action)
  151. format_menu.addAction(self.italic_action)
  152. self.underline_action = QAction(QIcon(os.path.join('images', 'edit-underline.png')), "下划线", self)
  153. self.underline_action.setStatusTip("将选定内容加下划线..")
  154. self.underline_action.setShortcut(QKeySequence.Underline)
  155. self.underline_action.setCheckable(True)
  156. self.underline_action.toggled.connect(self.editor.setFontUnderline)
  157. format_toolbar.addAction(self.underline_action)
  158. format_menu.addAction(self.underline_action)
  159. format_menu.addSeparator()
  160. self.alignl_action = QAction(QIcon(os.path.join('images', 'edit-alignment.png')), "靠左对齐", self)
  161. self.alignl_action.setStatusTip("将文本靠左对齐..")
  162. self.alignl_action.setCheckable(True)
  163. self.alignl_action.triggered.connect(lambda: self.editor.setAlignment(Qt.AlignLeft))
  164. format_toolbar.addAction(self.alignl_action)
  165. format_menu.addAction(self.alignl_action)
  166. self.alignc_action = QAction(QIcon(os.path.join('images', 'edit-alignment-center.png')), "居中对齐", self)
  167. self.alignc_action.setStatusTip("将文本居中对齐..")
  168. self.alignc_action.setCheckable(True)
  169. self.alignc_action.triggered.connect(lambda: self.editor.setAlignment(Qt.AlignCenter))
  170. format_toolbar.addAction(self.alignc_action)
  171. format_menu.addAction(self.alignc_action)
  172. self.alignr_action = QAction(QIcon(os.path.join('images', 'edit-alignment-right.png')), "靠右对齐", self)
  173. self.alignr_action.setStatusTip("将文本靠右对齐..")
  174. self.alignr_action.setCheckable(True)
  175. self.alignr_action.triggered.connect(lambda: self.editor.setAlignment(Qt.AlignRight))
  176. format_toolbar.addAction(self.alignr_action)
  177. format_menu.addAction(self.alignr_action)
  178. self.alignj_action = QAction(QIcon(os.path.join('images', 'edit-alignment-justify.png')), "对齐", self)
  179. self.alignj_action.setStatusTip("分散对齐文本..")
  180. self.alignj_action.setCheckable(True)
  181. self.alignj_action.triggered.connect(lambda: self.editor.setAlignment(Qt.AlignJustify))
  182. format_toolbar.addAction(self.alignj_action)
  183. format_menu.addAction(self.alignj_action)
  184. format_group = QActionGroup(self)
  185. format_group.setExclusive(True)
  186. format_group.addAction(self.alignl_action)
  187. format_group.addAction(self.alignc_action)
  188. format_group.addAction(self.alignr_action)
  189. format_group.addAction(self.alignj_action)
  190. format_menu.addSeparator()
  191. self._format_actions = [
  192. self.fonts,
  193. self.fontsize,
  194. self.bold_action,
  195. self.italic_action,
  196. self.underline_action]
  197. self.update_format()
  198. self.update_title()
  199. self.show()
  200. def block_signals(self, objects, b):
  201. for o in objects:
  202. o.blockSignals(b)
  203. def update_format(self):
  204. self.block_signals(self._format_actions, True)
  205. self.fonts.setCurrentFont(self.editor.currentFont())
  206. self.fontsize.setCurrentText(str(int(self.editor.fontPointSize())))
  207. self.italic_action.setChecked(self.editor.fontItalic())
  208. self.underline_action.setChecked(self.editor.fontUnderline())
  209. self.bold_action.setChecked(self.editor.fontWeight() == QFont.Bold)
  210. self.alignl_action.setChecked(self.editor.alignment() == Qt.AlignLeft)
  211. self.alignc_action.setChecked(self.editor.alignment() == Qt.AlignCenter)
  212. self.alignr_action.setChecked(self.editor.alignment() == Qt.AlignRight)
  213. self.alignj_action.setChecked(self.editor.alignment() == Qt.AlignJustify)
  214. self.block_signals(self._format_actions, False)
  215. def dialog_critical(self, s):
  216. dlg = QMessageBox(self)
  217. dlg.setText(s)
  218. dlg.setIcon(QMessageBox.Critical)
  219. dlg.show()
  220. def file_open(self):
  221. path, _ = QFileDialog.getOpenFileName(self, "Open file", "", "HTML documents (*.html);Text documents (*.txt);All files (*.*)")
  222. try:
  223. with open(path, 'rU') as f:
  224. text = f.read()
  225. except Exception as e:
  226. self.dialog_critical(str(e))
  227. else:
  228. self.path = path
  229. self.editor.setText(text)
  230. self.update_title()
  231. def file_save(self):
  232. if self.path is None:
  233. return self.file_saveas()
  234. text = self.editor.toHtml() if splitext(self.path) in HTML_EXTENSIONS else self.editor.toPlainText()
  235. try:
  236. with open(self.path, 'w') as f:
  237. f.write(text)
  238. except Exception as e:
  239. self.dialog_critical(str(e))
  240. def file_saveas(self):
  241. path, _ = QFileDialog.getSaveFileName(self, "Save file", "", "HTML documents (*.html);Text documents (*.txt);All files (*.*)")
  242. if not path:
  243. return
  244. text = self.editor.toHtml() if splitext(path) in HTML_EXTENSIONS else self.editor.toPlainText()
  245. try:
  246. with open(path, 'w') as f:
  247. f.write(text)
  248. except Exception as e:
  249. self.dialog_critical(str(e))
  250. else:
  251. self.path = path
  252. self.update_title()
  253. def file_print(self):
  254. dlg = QPrintDialog()
  255. if dlg.exec_():
  256. self.editor.print_(dlg.printer())
  257. def update_title(self):
  258. self.setWindowTitle("%s - 轩氏记事本 XuanNotepad" % (os.path.basename(self.path) if self.path else "Untitled"))
  259. def edit_toggle_wrap(self):
  260. self.editor.setLineWrapMode( 1 if self.editor.lineWrapMode() == 0 else 0 )
  261. if __name__ == '__main__':
  262. app = QApplication(sys.argv)
  263. app.setApplicationName("轩氏记事本 XuanNotepad")
  264. window = MainWindow()
  265. window.resize(1300,750)
  266. app.exec_()

 


>>> 本期pyqt5制作文本编辑器就到这里了,如有问题可以私聊。我们下期不见不散~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/816775
推荐阅读
相关标签
  

闽ICP备14008679号