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