欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-17 09:04:28
本文通过python3+pyqt5实现《python qt gui 快速编程》这本书13章程序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文本的行编辑方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

上一篇:

下一篇: