gpt4 book ai didi

python - QLabel setMinimumHeight 在自定义 WordWrap Qt.TextWrapAnywhere PyQt5 之后(完全响应有/没有表情符号)

转载 作者:行者123 更新时间:2023-12-05 03:31:14 24 4
gpt4 key购买 nike

我想在布局中为我的 QLabel 使用 Qt.TextWrapAnywhere

我关注了This指令。我的代码也一样,给出一个最小的代码

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QStyleOption, QVBoxLayout, QWidget, QStyle

class SuperQLabel(QLabel):
def __init__(self, *args, **kwargs):
super(SuperQLabel, self).__init__(*args, **kwargs)

self.textalignment = Qt.AlignLeft | Qt.TextWrapAnywhere
self.isTextLabel = True
self.align = None

def paintEvent(self, event):

opt = QStyleOption()
opt.initFrom(self)
painter = QPainter(self)

self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self)

self.style().drawItemText(painter, self.rect(),
self.textalignment, self.palette(), True, self.text())


class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)

self.resize(100, 200)

self.label = QLabel()
self.label.setWordWrap(True)
self.label.setText("11111111111111111111\n2222222211111111")

self.slabel = SuperQLabel()
self.slabel.setMinimumWidth(10)
self.slabel.setText("111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")

self.centralwidget = QWidget()
self.setCentralWidget(self.centralwidget)

self.mainlayout = QVBoxLayout()
self.mainlayout.addWidget(self.label)
self.mainlayout.addWidget(self.slabel)

self.centralwidget.setLayout(self.mainlayout)


if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

我对代码 self.slabel.setMinimumWidth(10) 做了一点改动,否则根据宽度调整 Label 大小将不起作用。

它根据宽度完美地包裹文本。但问题是当考虑高度时 self.label = QLabel() 正常 QLabel 会根据布局内容自动调整高度。

例如,如果我添加一个 \n,其中包含意味着 Qlabel 必须显示 2 行的文本。

但是有了这个新的自定义标签,例如self.slabel = SuperQLabel(),只要布局中有高度空间,包装就很好。我想我必须使用 setminimumHeight() 但不知道如何在自定义包装后获得正确的高度。

最佳答案

只要标签显示在滚动区域(不会对顶层布局造成问题),更好的解决方案是使用 QTextEdit 子类,配置如下:

  • readOnly 必须为 True;
  • 禁用滚动条;
  • 垂直尺寸政策必须是Preferred(而不是Expanding);
  • minimumSizeHint()sizeHint() 都应使用内部 QTextDocument 返回适当的高度,并具有最小默认宽度;
  • 任何大小或内容的变化都必须触发updateGeometry()这样父布局就会知道提示已更改并且可以再次计算几何图形;
  • 提示必须包括滚动区域的可能装饰(这是一个 QFrame);

这允许避免 paintEvent() 重写,并且由于 QTextDocument 提供的特性而提供更好和更容易的大小机制实现,同时将递归的可能性最小化到可接受的水平。

class WrapLabel(QtWidgets.QTextEdit):
def __init__(self, text=''):
super().__init__(text)
self.setStyleSheet('''
WrapLabel {
border: 1px outset palette(dark);
border-radius: 8px;
background: palette(light);
}
''')
self.setReadOnly(True)
self.setSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Maximum)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.textChanged.connect(self.updateGeometry)

def minimumSizeHint(self):
doc = self.document().clone()
doc.setTextWidth(self.viewport().width())
height = doc.size().height()
height += self.frameWidth() * 2
return QtCore.QSize(50, height)

def sizeHint(self):
return self.minimumSizeHint()

def resizeEvent(self, event):
super().resizeEvent(event)
self.updateGeometry()


class ChatTest(QtWidgets.QScrollArea):
def __init__(self):
super().__init__()
self.messages = []

container = QtWidgets.QWidget()
self.setWidget(container)
self.setWidgetResizable(True)

layout = QtWidgets.QVBoxLayout(container)
layout.addStretch()
self.resize(480, 360)

for i in range(1, 11):
QtCore.QTimer.singleShot(1000 * i, lambda:
self.addMessage('1' * randrange(100, 250)))

def addMessage(self, text):
self.widget().layout().addWidget(WrapLabel(text))
QtCore.QTimer.singleShot(0, self.scrollToBottom)

def scrollToBottom(self):
QtWidgets.QApplication.processEvents()
self.verticalScrollBar().setValue(
self.verticalScrollBar().maximum())

更新:HTML 和 QTextDocument

当使用 setHtml()setDocument() 时,源代码可能有不允许换行的 pre 格式文本。为避免这种情况,有必要遍历所有 QTextBlocks的文件,得到他们的QTextBlockFormat , 检查 nonBreakableLines()属性并最终将其设置为 False 并将格式设置回 QTextCursor .

class WrapLabel(QtWidgets.QTextEdit):
def __init__(self, text=None):
super().__init__()
if isinstance(text, str):
if Qt.mightBeRichText(text):
self.setHtml(text)
else:
self.setPlainText(text)
elif isinstance(text, QtGui.QTextDocument):
self.setDocument(text)
# ...

def setHtml(self, html):
doc = QtGui.QTextDocument()
doc.setHtml(html)
self.setDocument(doc)

def setDocument(self, doc):
doc = doc.clone()
tb = doc.begin() # start a QTextBlock iterator
while tb.isValid():
fmt = tb.blockFormat()
if fmt.nonBreakableLines():
fmt.setNonBreakableLines(False)
# create a QTextCursor for the current text block,
# then set the updated format to override the wrap
tc = QtGui.QTextCursor(tb)
tc.setBlockFormat(fmt)
tb = tb.next()
super().setDocument(doc)

但是请注意,当使用具有预定义或最小宽度的对象时,这还不够:图像和表格。结果将是,如果对象大于可用空间,它将在右侧裁剪(或从 RightToLeft 文本布局的左侧裁剪)。

关于python - QLabel setMinimumHeight 在自定义 WordWrap Qt.TextWrapAnywhere PyQt5 之后(完全响应有/没有表情符号),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70707523/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com