当前位置: 移动技术网 > IT编程>脚本编程>Python > python3+PyQt5 实现Rich文本的行编辑方法

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

2019年07月19日  | 移动技术网IT编程  | 我要评论

屠焱,崇左政府,袁郑健博客

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网