python3+PyQt5 实现Rich文本的行编辑方法
作者:basisworker 发布时间:2023-09-29 14:37:47
标签: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_()
来源:https://blog.csdn.net/xiaoyangyang20/article/details/68924261


猜你喜欢
- python一直被病垢运行速度太慢,但是实际上python的执行效率并不慢,慢的是python用的解释器Cpython运行效率太差。“一行代
- 本文实例讲述了Python常见数据结构之栈与队列用法。分享给大家供大家参考,具体如下:Python常见数据结构之-栈首先,栈是一种数据结构。
- 场景产品中有一张图片表pics,数据量将近100万条,有一条相关的查询语句,由于执行频次较高,想针对此语句进行优化表结构很简单,主要字段:u
- 网上的SQL优化的文章实在是很多,说实在的,我也曾经到处找这样的文章,什么不要使用IN了,什么OR了,什么AND了,很多很多,还有很多人拿出
- SQL Server中加密是层级的,每一个上层为下提供保护。如图:实例:/** SMK(Service Master Key)在SQL Se
- 在mysql中timestamp数据类型是一个比较特殊的数据类型,他可以自动在你不使用程序更新情况下只要你更新了记录timestamp会自动
- 如下所示:def findSmallest(arr): smallest = arr[0]#将第一个元素的值作为最小值赋给smallest
- 本文所依赖的环境为:进程和线程的概念进程概念我们想运行一个程序,首先会将该程序从存储介质上通过IO总线加载进内存中,而后再通过cpu进行调度
- 软件环境: 1、操作系统:Windows 2000 Server 2、数 据 库:Oracle 8i R2 (8.1.7) for NT 企
- 问题:编写一个在1,2,…,9(顺序不能变)数字之间插入+或-或什么都不插入,使得计算结果总是100的程序,并输出所有的可能性。例如:1 +
- WHERE 条件有时候操作数据库时,只操作一些有条件限制的数据,这时可以在SQL语句中添加WHERE子句来规定数据操作的条件。语法:SELE
- Tensorflow可以使用训练好的模型对新的数据进行测试,有两种方法:第一种方法是调用模型和训练在同一个py文件中,中情况比较简单;第二种
- python自带了日志模块logging,可以用来记录程序运行过程中的日志信息。同时python还有logbook模块用来取代logging
- 前言(结尾有彩蛋欧)目前,许多网站采取各种各样的措施来反爬虫,其中一个措施便是使用验证码。随着技术的发展,验证码的花样越来越多。验证码最初是
- 要想从命令行启动mysqld服务器,你应当启动控制台窗口(或“DOS window”)并输入命令:C
- 代码return JsonResponse({"name": "tom"})报错:TYPEERROR
- 完整性约束是对字段进行限制,从而符合该字段达到我们期望的效果比如字段含有默认值,不能是NULL等 直观点说:如果插入的数据不满足限制要求,数
- 双向链表一种更复杂的链表是“双向链表”或“双面链表”。每个节
- Python实现多进程间通信的方式有很多种,例如队列,管道等。但是这些方式只适用于多个进程都是源于同一个父进程的情况。如果多个进程不是源于同
- 概述结构体是由一系列具有相同类型或不同类型的数据构成的数据集合语法定义结构体【标识自定义结构体的名称,在同一个包内不能重复】type 结构名