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 相关文章推荐
在Django框架中编写Contact表单的教程
Jul 17 Python
python登录并爬取淘宝信息代码示例
Dec 09 Python
Python实现将数据写入netCDF4中的方法示例
Aug 30 Python
Python实现简单层次聚类算法以及可视化
Mar 18 Python
Matplotlib绘制雷达图和三维图的示例代码
Jan 07 Python
Python字典dict常用方法函数实例
Nov 09 Python
Python 微信公众号文章爬取的示例代码
Nov 30 Python
基于 Python 实践感知器分类算法
Jan 07 Python
Python3 使用pip安装git并获取Yahoo金融数据的操作
Apr 08 Python
python 用递归实现通用爬虫解析器
Apr 16 Python
再也不用花钱买漫画!Python爬取某漫画的脚本及源码
Jun 09 Python
Pandas实现DataFrame的简单运算、统计与排序
Mar 31 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
人大复印资料处理程序_补充篇
2006/10/09 PHP
在PHP中使用反射技术的架构插件使用说明
2010/05/18 PHP
php结合表单实现一些简单功能的例子
2011/06/04 PHP
PHP学习笔记之数组篇
2011/06/28 PHP
async和DOM Script文件加载比较
2014/07/20 PHP
CI框架AR操作(数组形式)实现插入多条sql数据的方法
2016/05/18 PHP
PHP检测一个数组有没有定义的方法步骤
2019/07/20 PHP
使用js获取地址栏中传递的值
2013/07/02 Javascript
jquery购物车实时结算特效实现思路
2013/09/23 Javascript
JavaScript实现的一个倒计时的类
2015/03/12 Javascript
PHP+jQuery实现随意拖动层并即时保存拖动位置
2015/04/30 Javascript
基于jQuery倾斜打开侧边栏菜单特效代码
2015/09/15 Javascript
基于ajax和jsonp的原生封装(实例)
2017/10/16 Javascript
微信小程序日期选择器实例代码
2018/07/18 Javascript
学习RxJS之JavaScript框架Cycle.js
2019/06/17 Javascript
基于js实现数组相邻元素上移下移
2020/05/19 Javascript
python实现发送邮件功能代码
2017/12/14 Python
Python与人工神经网络:使用神经网络识别手写图像介绍
2017/12/19 Python
Python logging模块异步线程写日志实现过程解析
2020/06/30 Python
重构Python代码的六个实例
2020/11/25 Python
Python函数调用追踪实现代码
2020/11/27 Python
Python爬虫之Selenium库的使用方法
2021/01/03 Python
HTML5 Canvas概述
2009/08/26 HTML / CSS
日本乐天德国站:Rakuten.de
2019/05/16 全球购物
英国时尚高尔夫服装购物网站:Trendy Golf
2020/01/10 全球购物
新闻学毕业生自荐信
2013/11/15 职场文书
教师实习自我鉴定
2013/12/13 职场文书
勤奋学习演讲稿
2014/05/10 职场文书
社区两委对照检查材料
2014/08/23 职场文书
考试没考好检讨书
2015/05/06 职场文书
矛盾论读书笔记
2015/06/29 职场文书
高一数学教学反思
2016/02/18 职场文书
《夜莺的歌声》教学反思
2016/02/22 职场文书
2016年学校爱国卫生月活动总结
2016/04/06 职场文书
八年级地理课件资料及考点知识分享
2019/08/30 职场文书
ElementUI实现el-form表单重置功能按钮
2021/07/21 Javascript