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


Posted in Python onJune 17, 2019

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

#!/usr/bin/env python3

import platform
import sys
import html
from PyQt5.QtCore import QSize, Qt,pyqtSignal
from PyQt5.QtGui import QColor, QFont,QFontMetrics, QIcon, QKeySequence, QPixmap,QTextCharFormat
from PyQt5.QtWidgets import QAction,QApplication,QMenu,QTextEdit



class 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 htmltext

if __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文本的行编辑方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python代码 if not x: 和 if x is not None: 和 if not x is None:使用介绍
Sep 21 Python
Python cookbook(数据结构与算法)实现优先级队列的方法示例
Feb 18 Python
Python之pandas读写文件乱码的解决方法
Apr 20 Python
基于python 爬虫爬到含空格的url的处理方法
May 11 Python
python利用smtplib实现QQ邮箱发送邮件
May 20 Python
python3爬取数据至mysql的方法
Jun 26 Python
Python+pandas计算数据相关系数的实例
Jul 03 Python
python批量将excel内容进行翻译写入功能
Oct 10 Python
python 在右键菜单中加入复制目标文件的有效存放路径(单斜杠或者双反斜杠)
Apr 08 Python
为什么说python更适合树莓派编程
Jul 20 Python
selenium判断元素是否存在的两种方法小结
Dec 07 Python
Python字节单位转换(将字节转换为K M G T)
Mar 02 Python
Appium+python自动化之连接模拟器并启动淘宝APP(超详解)
Jun 17 #Python
python3+PyQt5 数据库编程--增删改实例
Jun 17 #Python
python3+PyQt5 创建多线程网络应用-TCP客户端和TCP服务器实例
Jun 17 #Python
python 应用之Pycharm 新建模板默认添加编码格式-作者-时间等信息【推荐】
Jun 17 #Python
python3+PyQt5 使用三种不同的简便项窗口部件显示数据的方法
Jun 17 #Python
对PyQt5中树结构的实现方法详解
Jun 17 #Python
PyQT实现菜单中的复制,全选和清空的功能的方法
Jun 17 #Python
You might like
漫威DC御用漫画家去世 他的表情包曾走红网络
2020/04/09 欧美动漫
如何过滤高亮显示非法字符
2006/10/09 PHP
Joomla下利用configuration.php存储简单数据
2010/05/19 PHP
php include加载文件两种方式效率比较
2010/08/08 PHP
7个超级实用的PHP代码片段
2011/07/11 PHP
安装ImageMagick出现error while loading shared libraries的解决方法
2014/09/23 PHP
WIFI万能钥匙密码查询接口实例
2015/09/28 PHP
在Mac OS的PHP环境下安装配置MemCache的全过程解析
2016/02/15 PHP
ExtJS Grid使用SimpleStore、多选框的方法
2009/11/20 Javascript
原始的js代码和jquery对比体会
2013/09/10 Javascript
jQuery实现平滑滚动页面到指定锚点链接的方法
2015/07/15 Javascript
jquery插件tytabs.jquery.min.js实现渐变TAB选项卡效果
2015/08/25 Javascript
JavaScript中this详解
2015/09/01 Javascript
jquery插件jquery.LightBox.js实现点击放大图片并左右点击切换效果(附demo源码下载)
2016/02/25 Javascript
Bootstrap媒体对象的实现
2016/05/01 Javascript
TinyMCE汉化及本地上传图片功能实例详解
2016/05/31 Javascript
微信小程序实现发送验证码按钮效果
2018/12/20 Javascript
Node.js + express基本用法教程
2019/03/14 Javascript
基于Node的Axure文件在线预览的实现代码
2019/08/28 Javascript
Vue+Bootstrap收藏(点赞)功能逻辑与具体实现
2020/10/22 Javascript
python数据结构之二叉树的统计与转换实例
2014/04/29 Python
Python实现的一个简单LRU cache
2014/09/26 Python
用Python解决计数原理问题的方法
2016/08/04 Python
同时安装Python2 &amp; Python3 cmd下版本自由选择的方法
2017/12/09 Python
Django migrations 默认目录修改的方法教程
2018/09/28 Python
英国女性时尚品牌:Apricot
2018/12/04 全球购物
生产厂厂长岗位职责
2013/12/25 职场文书
房屋买卖协议书
2014/04/10 职场文书
交通事故协议书范文
2014/04/16 职场文书
课外活动实习计划
2015/01/19 职场文书
办公室主任个人总结
2015/02/28 职场文书
乔布斯辞职信(中英文对照)
2015/05/12 职场文书
如何书写先进事迹材料?
2019/07/02 职场文书
python中的None与NULL用法说明
2021/05/25 Python
用Python爬取各大高校并可视化帮弟弟选大学,弟弟直呼牛X
2021/06/11 Python
Python 文字识别
2022/05/11 Python