首页 > 编程 > Python > 正文

python3+PyQt5 实现Rich文本的行编辑方法

2019-11-25 12:44:29
字体:
来源:转载
供稿:网友

本文通过Python3+PyQt5实现《python Qt Gui 快速编程》这本书13章程序Rich文本的行编辑,可以通过鼠标右键选择对文本进行加粗,斜体,下划线,删除线,上标,下标等编辑。

#!/usr/bin/env python3import platformimport sysimport htmlfrom PyQt5.QtCore import QSize, Qt,pyqtSignalfrom PyQt5.QtGui import QColor, QFont,QFontMetrics, QIcon, QKeySequence, QPixmap,QTextCharFormatfrom PyQt5.QtWidgets import QAction,QApplication,QMenu,QTextEditclass RichTextLineEdit(QTextEdit):  returnPressed=pyqtSignal()  (Bold, Italic, Underline, StrikeOut, Monospaced, Sans, Serif,   NoSuperOrSubscript, Subscript, Superscript) = range(10)  def __init__(self, parent=None):    super(RichTextLineEdit, self).__init__(parent)    self.monofamily = "courier"    self.sansfamily = "helvetica"    self.seriffamily = "times"    self.setLineWrapMode(QTextEdit.NoWrap)    self.setTabChangesFocus(True)    self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)    self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)    fm = QFontMetrics(self.font())    h = int(fm.height() * (1.4 if platform.system() == "Windows"                  else 1.2))    self.setMinimumHeight(h)    self.setMaximumHeight(int(h * 1.2))    self.setToolTip("Press <b>Ctrl+M</b> for the text effects "        "menu and <b>Ctrl+K</b> for the color menu")  def toggleItalic(self):    self.setFontItalic(not self.fontItalic())  def toggleUnderline(self):    self.setFontUnderline(not self.fontUnderline())  def toggleBold(self):    self.setFontWeight(QFont.Normal        if self.fontWeight() > QFont.Normal else QFont.Bold)  def sizeHint(self):    return QSize(self.document().idealWidth() + 5,           self.maximumHeight())  def minimumSizeHint(self):    fm = QFontMetrics(self.font())    return QSize(fm.width("WWWW"), self.minimumHeight())  def contextMenuEvent(self, event):    self.textEffectMenu()  def keyPressEvent(self, event):    if event.modifiers() & Qt.ControlModifier:      handled = False      if event.key() == Qt.Key_B:        self.toggleBold()        handled = True      elif event.key() == Qt.Key_I:        self.toggleItalic()        handled = True      elif event.key() == Qt.Key_K:        self.colorMenu()        handled = True      elif event.key() == Qt.Key_M:        self.textEffectMenu()        handled = True      elif event.key() == Qt.Key_U:        self.toggleUnderline()        handled = True      if handled:        event.accept()        return    if event.key() in (Qt.Key_Enter, Qt.Key_Return):      self.returnPressed.emit()      event.accept()    else:      QTextEdit.keyPressEvent(self, event)  def colorMenu(self):    pixmap = QPixmap(22, 22)    menu = QMenu("Colour")    for text, color in (        ("&Black", Qt.black),        ("B&lue", Qt.blue),        ("Dark Bl&ue", Qt.darkBlue),        ("&Cyan", Qt.cyan),        ("Dar&k Cyan", Qt.darkCyan),        ("&Green", Qt.green),        ("Dark Gr&een", Qt.darkGreen),        ("M&agenta", Qt.magenta),        ("Dark Mage&nta", Qt.darkMagenta),        ("&Red", Qt.red),        ("&Dark Red", Qt.darkRed)):      color = QColor(color)      pixmap.fill(color)      action = menu.addAction(QIcon(pixmap), text, self.setColor)      action.setData(color)    self.ensureCursorVisible()    menu.exec_(self.viewport().mapToGlobal(          self.cursorRect().center()))  def setColor(self):    action = self.sender()    if action is not None and isinstance(action, QAction):      color = QColor(action.data())      if color.isValid():        self.setTextColor(color)  def textEffectMenu(self):    format = self.currentCharFormat()    menu = QMenu("Text Effect")    for text, shortcut, data, checked in (        ("&Bold", "Ctrl+B", RichTextLineEdit.Bold,         self.fontWeight() > QFont.Normal),        ("&Italic", "Ctrl+I", RichTextLineEdit.Italic,         self.fontItalic()),        ("Strike &out", None, RichTextLineEdit.StrikeOut,         format.fontStrikeOut()),        ("&Underline", "Ctrl+U", RichTextLineEdit.Underline,         self.fontUnderline()),        ("&Monospaced", None, RichTextLineEdit.Monospaced,         format.fontFamily() == self.monofamily),        ("&Serifed", None, RichTextLineEdit.Serif,         format.fontFamily() == self.seriffamily),        ("S&ans Serif", None, RichTextLineEdit.Sans,         format.fontFamily() == self.sansfamily),        ("&No super or subscript", None,         RichTextLineEdit.NoSuperOrSubscript,         format.verticalAlignment() ==         QTextCharFormat.AlignNormal),        ("Su&perscript", None, RichTextLineEdit.Superscript,         format.verticalAlignment() ==         QTextCharFormat.AlignSuperScript),        ("Subs&cript", None, RichTextLineEdit.Subscript,         format.verticalAlignment() ==         QTextCharFormat.AlignSubScript)):      action = menu.addAction(text, self.setTextEffect)      if shortcut is not None:        action.setShortcut(QKeySequence(shortcut))      action.setData(data)      action.setCheckable(True)      action.setChecked(checked)    self.ensureCursorVisible()    menu.exec_(self.viewport().mapToGlobal(          self.cursorRect().center()))  def setTextEffect(self):    action = self.sender()    if action is not None and isinstance(action, QAction):      what = action.data()      if what == RichTextLineEdit.Bold:        self.toggleBold()        return      if what == RichTextLineEdit.Italic:        self.toggleItalic()        return      if what == RichTextLineEdit.Underline:        self.toggleUnderline()        return      format = self.currentCharFormat()      if what == RichTextLineEdit.Monospaced:        format.setFontFamily(self.monofamily)      elif what == RichTextLineEdit.Serif:        format.setFontFamily(self.seriffamily)      elif what == RichTextLineEdit.Sans:        format.setFontFamily(self.sansfamily)      if what == RichTextLineEdit.StrikeOut:        format.setFontStrikeOut(not format.fontStrikeOut())      if what == RichTextLineEdit.NoSuperOrSubscript:        format.setVerticalAlignment(            QTextCharFormat.AlignNormal)      elif what == RichTextLineEdit.Superscript:        format.setVerticalAlignment(            QTextCharFormat.AlignSuperScript)      elif what == RichTextLineEdit.Subscript:        format.setVerticalAlignment(            QTextCharFormat.AlignSubScript)      self.mergeCurrentCharFormat(format)  def toSimpleHtml(self):    htmltext = ""    black = QColor(Qt.black)    block = self.document().begin()    while block.isValid():      iterator = block.begin()      while iterator != block.end():        fragment = iterator.fragment()        if fragment.isValid():          format = fragment.charFormat()          family = format.fontFamily()          color = format.foreground().color()                   text=html.escape(fragment.text())          if (format.verticalAlignment() ==            QTextCharFormat.AlignSubScript):            text = "<sub>{0}</sub>".format(text)          elif (format.verticalAlignment() ==             QTextCharFormat.AlignSuperScript):            text = "<sup>{0}</sup>".format(text)          if format.fontUnderline():            text = "<u>{0}</u>".format(text)          if format.fontItalic():            text = "<i>{0}</i>".format(text)          if format.fontWeight() > QFont.Normal:            text = "<b>{0}</b>".format(text)          if format.fontStrikeOut():            text = "<s>{0}</s>".format(text)          if color != black or family:            attribs = ""            if color != black:              attribs += ' color="{0}"'.format(color.name())            if family:              attribs += ' face="{0}"'.format(family)            text = "<font{0}>{1}</font>".format(attribs,text)          htmltext += text        iterator += 1      block = block.next()    return htmltextif __name__ == "__main__":  def printout(lineedit):    print(str(lineedit.toHtml()))    print(str(lineedit.toPlainText()))    print(str(lineedit.toSimpleHtml()))          app = QApplication(sys.argv)  lineedit = RichTextLineEdit()  lineedit.returnPressed.connect(lambda:printout(lineedit))  lineedit.show()  lineedit.setWindowTitle("RichTextEdit")  app.exec_()

以上这篇python3+PyQt5 实现Rich文本的行编辑方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表