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

本文通过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文本的行编辑方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 使用Python3+PyQT5+Pyserial 实现简单的串口工具方法

    练手项目,先上图 先实现一个简单的串口工具,为之后的上位机做准备 代码如下: github 下载地址 pyserial_demo.py import sys import serial import serial.tools.list_ports from PyQt5 import QtWidgets from PyQt5.QtWidgets import QMessageBox from PyQt5.QtCore import QTimer from ui_demo_1 import Ui_F

  • PyQt5每天必学之单行文本框

    本文实例为大家分享了PyQt5单行文本框展示的具体代码,供大家参考,具体内容如下 QLineEdit 是一个允许输入和编辑纯文本的单行控件.系统中的撤销.重做.复制.剪切和粘贴都可用于该控件. #!/usr/bin/python3 # -*- coding: utf-8 -*- """ PyQt5 教程 这个例子中,在QLineEdit中输入的文字实时的在QLabel中显示出来. 作者:我的世界你曾经来过 博客:http://blog.csdn.net/weiaitaowan

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

    本文通过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,QFontM

  • python3+pyqt5+itchat微信定时发送消息的方法

    编这个程序是想过节过年,一些重要的纪念日,给亲戚好友发祝福之类的,但要凌晨0点才显得比较有诚意,可我又比较贪睡,常常忘了,所以就有了编个微信定时发送消息小程序. 运行环境: python 3.x,不支持python2 准备工作 由于我用到了微信的接口,所以引入itchat 界面用了pyqt5 安装命令如下: pip install PyQt5 pip install itchat 代码部分 # -*- coding: utf-8 -*- # @Time : 2018/9/25 11:06 # @

  • python3+PyQt5 使用三种不同的简便项窗口部件显示数据的方法

    本文通过将同一个数据集在三种不同的简便项窗口部件中显示.三个窗口的数据得到实时的同步,数据和视图分离.当添加或删除数据行,三个不同的视图均保持同步.数据将保存在本地文件中,而非数据库.对于小型和临时性数据集来说,这些简便窗口部件非常有用,可以用在非单独数据集中-数据自身的显示,编辑和存储. 所使用的数据集: /home/yrd/eric_workspace/chap14/ships_conv/ships.py #!/usr/bin/env python3 import platform from

  • python3+PyQt5图形项的自定义和交互 python3实现page Designer应用程序

    本文通过Python3+PyQt5实现<python Qt Gui 快速编程>这本书的page Designer应用程序,采用QGraphicsView,QGraphicsScene,QGraphicsItem,这个程序包含有多个文本,图片和框的页面.有些图形类在PyQt5已过时,所以本代码改动幅度比较大.主要的类或方法的改变如下: QMatrix==>QTransform setMatrix==>setTransform rotate ==> setRotation 本例中

  • Python3实现从文件中读取指定行的方法

    本文实例讲述了Python3实现从文件中读取指定行的方法.分享给大家供大家参考.具体实现方法如下: # Python的标准库linecache模块非常适合这个任务 import linecache the_line = linecache.getline('d:/FreakOut.cpp', 222) print (the_line) # linecache读取并缓存文件中所有的文本, # 若文件很大,而只读一行,则效率低下. # 可显示使用循环, 注意enumerate从0开始计数,而line

  • python3+PyQt5实现使用剪贴板做复制与粘帖示例

    本文是对<Python Qt GUI快速编程>的第10章的例子剪贴板用Python3+PyQt5进行改写,分别对文本,图片和html文本的复制与粘帖,三种做法大同小异. #!/usr/bin/env python3 import os import sys from PyQt5.QtCore import (QMimeData, Qt) from PyQt5.QtWidgets import (QApplication, QDialog, QGridLayout, QLabel, QPushB

  • python3.4.3下逐行读入txt文本并去重的方法

    读写文件时应注意的问题包括: 1.字符编码 2.操作完成即时关闭文件描述符 3.代码兼容性 几种方法: #!/bin/python3 original_list1=[" "] original_list2=[" "] original_list3=[" "] original_list4=[" "] newlist1=[" "] newlist2=[" "] newlist3=[&quo

  • 基于python3 pyQt5 QtDesignner实现窗口化猜数字游戏功能

    描述:使用QtDesignner设计界面,pyQt5+python3实现主体方法制作的猜数字游戏. 游戏规则:先选择游戏等级:初级.中级.高级.魔鬼级,选择完游戏等级后点击"确定",然后后台会自动生成一个与游戏等级匹配的"神秘数字",游戏玩家在文本框内输入数字,再点击文本框旁边的"确定",即可比较玩家所猜数字是否就是"神秘数字". 游戏界面: 源代码: 代码1: guessNumberGame.py (界面代码) # -*-

  • python3+PyQt5+Qt Designer实现界面可视化

    前言 以前制作一个Python窗体界面,我都是用GUI窗口视窗设计的模块Tkinter一点一点敲出来的,今天朋友问我有没有Python窗体的设计工具,"用鼠标拖拖"就能完成窗体设计,我查了查相关资料,果然有一款好用的工具--Qt Designer. 1.安装Qt Designer 这里需要安装两个东西:PyQt5和PyQt5-tools: 安装PyQt5:打开CMD或者PowerShell,在命令窗中输入 pip install PyQt5 执行结果如下: 安装PyQt5-tools:

随机推荐