我发现@Eric Hulser 的回答虽然很棒,但在将标签放入另一个小部件时不起作用。
我通过将 Eric 的响应和 Qt Elided Label Example结合起来想出了这个。如此处所写,它允许传入不同的省略模式并垂直保留文本(当然,它是水平省略的!)。
根据文档实现的布局阶段对我来说并不清楚,所以我不能很好地说明这一点。基本上,它会检查标签文本是否没有超出标签的宽度;如果是这样,它会省略文本。
也不清楚“有效”行是什么意思。删除这些检查会导致应用程序崩溃。我的猜测是,当它没有超出小部件时,这条线是有效的。
如果你想使用 PySide,
- PyQt5 -> PySide2
- pyqtSignal -> 信号
总之,享受吧!
import sys
from PyQt5 import QtCore, QtWidgets, QtGui
class EliderLabel(QtWidgets.QLabel):
elision_changed = QtCore.pyqtSignal(bool)
def __init__(self, text='', mode=QtCore.Qt.ElideRight, **kwargs):
super().__init__(**kwargs)
self._mode = mode
self.elided = False
self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
self.setText(text)
def setText(self, text):
self._contents = text
# Changing the content require a repaint of the widget (or so
# says the overview)
self.update()
def text(self):
return self._contents
def minimumSizeHint(self):
metrics = QtGui.QFontMetrics(self.font())
return QtCore.QSize(0, metrics.height())
def paintEvent(self, event):
super().paintEvent(event)
did_elide = False
painter = QtGui.QPainter(self)
font_metrics = painter.fontMetrics()
# fontMetrics.width() is deprecated; use horizontalAdvance
text_width = font_metrics.horizontalAdvance(self.text())
# Layout phase, per the docs
text_layout = QtGui.QTextLayout(self._contents, painter.font())
text_layout.beginLayout()
while True:
line = text_layout.createLine()
if not line.isValid():
break
line.setLineWidth(self.width())
if text_width >= self.width():
elided_line = font_metrics.elidedText(self._contents, self._mode, self.width())
painter.drawText(QtCore.QPoint(0, font_metrics.ascent()), elided_line)
did_elide = line.isValid()
break
else:
line.draw(painter, QtCore.QPoint(0, 0))
text_layout.endLayout()
self.elision_changed.emit(did_elide)
if did_elide != self.elided:
self.elided = did_elide
self.elision_changed.emit(did_elide)
class MyDialog(QtWidgets.QWidget):
def __init__(self):
super().__init__()
text = 'This is a really, long and poorly formatted runon sentence used to illustrate a point'
label = EliderLabel(text, parent=self)
label.elision_changed.connect(self.on_elide)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(label)
self.setLayout(layout)
def on_elide(self, val):
print('Elided: ', val, flush=True)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
dia = MyDialog()
dia.show()
sys.exit(app.exec_())