如何使标签文本轮廓化并适合标签的大小
Posted
技术标签:
【中文标题】如何使标签文本轮廓化并适合标签的大小【英文标题】:How to make label text outlined AND fit the size of the label 【发布时间】:2021-04-14 14:20:02 【问题描述】:如何使标签文本被勾勒出来(以便在透明 Widget 上获得更好的可见性)并适合标签(根据函数 setWordWrap (True)?有一些示例说明如何做一个或另一个,但从不两者兼而有之。
透明小部件上的静态标签文本的基本示例是:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Application(QWidget):
def __init__(self):
super().__init__()
screen_size = QWidget.screen(self).size()
screen_width = screen_size.width()
screen_height = screen_size.height()
widget_width = screen_width * 0.30
self.setGeometry(100, 100, widget_width, screen_height)
self.move(screen_width - widget_width, 0)
self.setAttribute(Qt.WA_TransparentForMouseEvents)
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
| Qt.CustomizeWindowHint | Qt.Window)
l1 = QLabel(self)
l1.setWordWrap(True)
l1.setGeometry(0, 0, widget_width, screen_height)
l1.setFont(QFont('Arial', 22))
l1.setStyleSheet('color:rgb(0,255,0)')
l1.setText('Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello')
def render_the_app():
app = QApplication(sys.argv)
window = Application()
window.setAttribute(Qt.WA_TranslucentBackground)
window.show()
app.exec_()
render_the_app()
此代码示例将呈现绿色文本“Hello Hello ...”并呈现为: 在透明小部件上换行文本示例:
【问题讨论】:
感谢@eyllanesc 编辑问题。对于同样的错误,我深表歉意,但我不知道如何让这张图片看起来像你做的那样漂亮 注意:我建议您不要再做同样的事情(重新发布相同的帖子),因为系统可能会阻止创建帖子的能力。 知道了。由于作者和审稿人之间的交流有限——我仍然不知道其他 [已关闭] 帖子会发生什么,以及是否有人会重新打开。我进行了编辑并使其简短明了。与我在 SO 上看到的许多其他帖子相比,我觉得在编辑后我的帖子至少足够好,并且比许多帖子好。但是我看不到是不是有人审核了还是觉得不好,或者没有人再审核了,我需要等待更长的时间。 您多久之前改进了您的帖子?最多一天,你认为那是很长的时间吗?不,所以你必须学会更有耐心。如果您不想耐心等待,请从头开始分析您的帖子,以免最终关闭。建议想发帖的人花点时间写(小时),分析自己是否符合本站规则。 @eyllanesc 这很公平。第一篇文章的审核速度给我留下了深刻的印象(15-20 分钟内),所以在编辑后 12 个多小时后,我开始感到紧张。您也知道,如果您沉迷于某个想法但找不到解决方案 - 您可能会失去耐心。这不是借口,我会从中吸取教训。感谢您的反馈 【参考方案1】:使用画家路径是一个很好的解决方案,但它不允许对内容进行更精细的控制,特别是考虑到基于文本的小部件还应该提供正确的大小提示,并且可能允许自动换行。
另一方面,QTextDocument 被任何使用文本的 QWidget 子类(有时公开,如 QTextEdit,其他内部,如 QLabel)提供大纲功能,因此可能的解决方案是创建一个类部分模仿 QLabel,提供正确的大小提示和自动换行。
class Test(QtWidgets.QWidget):
_outlinePen = _alignment = None
def __init__(self, text='', parent=None, **kwargs):
super().__init__(parent)
self.doc = QtGui.QTextDocument()
self._reference = self.doc.clone()
self.doc.contentsChanged.connect(self._rebuildReference)
self._text = text
self._outlineColor = QtGui.QColor(kwargs.get('outlineColor'))
self._outlineWidth = kwargs.get('outlineWidth', 0)
if text:
self.doc.setPlainText(text)
self.updateContents()
def _rebuildReference(self):
self._reference = self.doc.clone()
def updateContents(self):
cursor = QtGui.QTextCursor(self.doc)
cursor.select(cursor.Document)
blockFmt = cursor.blockFormat()
blockFmt.setAlignment(self.alignment())
cursor.setBlockFormat(blockFmt)
charFmt = cursor.charFormat()
charFmt.setFont(self.font())
outlinePen = self.outlinePen()
if outlinePen:
charFmt.setTextOutline(outlinePen)
cursor.setCharFormat(charFmt)
self.updateGeometry()
self.adjustSize()
def text(self):
return self._text
def setText(self, text):
if self._text == text:
return
self.doc.setPlainText(text)
self.updateContents()
def outlinePen(self):
if isinstance(self._outlineColor, QtGui.QColor) and self._outlineColor.isValid():
pen = QtGui.QPen(self._outlineColor)
pen.setWidthF(self._outlineWidth or self.fontMetrics().lineWidth() * .25)
return pen
def setOutlinePen(self, pen):
self._outlineColor = pen.brush().color()
self._outlineWidth = pen.widthF()
self.updateContents()
def outlineColor(self):
return self._outlineColor
def setOutlineColor(self, color):
if self._outlineColor != color:
self._outlineColor = color
self.updateContents()
def outlineWidth(self):
return self._outlineWidth
def setOutlineWidth(self, width):
if self._outlineWidth != width:
self._outlineWidth = width
self.updateContents()
def alignment(self):
alignment = self._alignment
if not isinstance(alignment, (QtCore.Qt.Alignment, QtCore.Qt.AlignmentFlag)):
alignment = QtCore.Qt.AlignTop
if self.layoutDirection() == QtCore.Qt.LeftToRight:
alignment |= QtCore.Qt.AlignLeft
else:
alignment |= QtCore.Qt.AlignRight
return alignment
def setAlignment(self, alignment):
if self._alignment != alignment:
self._alignment = alignment
self.updateContents()
def changeEvent(self, event):
if event.type() == event.FontChange:
self.updateContents()
def sizeHint(self):
if self.isVisible():
doc = self._reference
doc.setTextWidth(self.width())
else:
doc = self.doc
return doc.size().toSize()
def paintEvent(self, event):
qp = QtGui.QPainter(self)
self._reference.setTextWidth(self.width())
self._reference.drawContents(qp, QtCore.QRectF(self.rect()))
【讨论】:
谢谢!我对 PyQt 很陌生,几乎不了解它的概念。将测试您的解决方案 我尝试了我的理解,但无法使其工作。它打印文本,但我无法让它进行换行或大纲。所以它只在一行中给我黑色文本。 我建议您使用我的代码原样尝试,无需任何修改,以查看其结果。请注意,Qt.WA_TranslucentBackground
属性可能是一个问题(我无法对其进行测试)。首先,按原样尝试(作为没有半透明属性的标准小部件),只是为了看看轮廓是否有效。然后,可能需要进行一些调整:半透明实现并不像看起来那样“透明”(双关语)。我强烈建议您使用循序渐进的方法,而不是试图立即使我的代码适应您的代码。以上是关于如何使标签文本轮廓化并适合标签的大小的主要内容,如果未能解决你的问题,请参考以下文章