python3+PyQt5 实现Rich文本的行编辑方法
作者:basisworker 时间:2023-09-29 14:37:47
本文通过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
标签:python3,PyQt5,Rich,文本,行编辑
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
浅谈Python NLP入门教程
2021-04-18 14:45:53
![](https://img.aspxhome.com/file/2023/2/84062_0s.jpg)
Python提取Word中图片的实现步骤
2022-11-07 20:25:10
![](https://img.aspxhome.com/file/2023/3/105723_0s.png)
go doudou开发gRPC服务快速上手实现详解
2024-05-05 09:33:11
![](https://img.aspxhome.com/file/2023/7/127467_0s.png)
python3读取文件指定行的三种方法
2023-03-23 12:27:20
Linux Centos 下使用yum 命令安装mysql实现步骤
2024-01-28 02:24:42
PHPMailer发送HTML内容、带附件的邮件实例
2024-05-11 10:07:43
![](https://img.aspxhome.com/file/2023/0/125780_0s.jpg)
详解Python用户登录接口的方法
2021-10-09 23:26:48
![](https://img.aspxhome.com/file/2023/1/93871_0s.jpg)
python自动分箱,计算woe,iv的实例代码
2022-10-13 22:51:50
![](https://img.aspxhome.com/file/2023/3/88013_0s.jpg)
Python实现的NN神经网络算法完整示例
2023-10-06 04:30:41
![](https://img.aspxhome.com/file/2023/2/63542_0s.png)
Vue3中如何使用异步请求示例详解
2024-04-27 16:04:56
![](https://img.aspxhome.com/file/2023/4/133014_0s.jpg)
mysql中in条件使用字符串方式
2024-01-28 02:24:55
vue使用nprogress加载路由进度条的方法
2024-05-02 17:02:22
![](https://img.aspxhome.com/file/2023/8/130078_0s.png)
Vue3异步数据加载组件suspense的使用方法
2024-04-30 10:46:09
Python反转序列的方法实例分析
2021-10-30 11:13:07
python实现三种随机请求头方式
2022-01-17 17:06:39
![](https://img.aspxhome.com/file/2023/5/81575_0s.png)
详解MySQL中的缓冲池(buffer pool)
2024-01-26 01:05:53
![](https://img.aspxhome.com/file/2023/7/87117_0s.png)
面试被问select......for update会锁表还是锁行
2024-01-17 20:59:17
![](https://img.aspxhome.com/file/2023/9/121579_0s.png)
Python实现列表中非负数保留,负数转化为指定的数值方式
2022-07-23 21:23:24
![](https://img.aspxhome.com/file/2023/6/99696_0s.jpg)
python Graham求凸包问题并画图操作
2023-06-01 12:37:00
Pandas Matplotlib保存图形时坐标轴标签太长导致显示不全问题的解决
2023-07-22 20:03:09
![](https://img.aspxhome.com/file/2023/0/62940_0s.png)