单线可删除QLabel

2024-09-30 18:27:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个Qlabel,它只会填充Qt中的可用空间(实际上是PyQt,但同样的原则也适用)。这意味着要显示一个(有时很长)文件路径,而我现在看到的标签的长度使得窗口部分的最小尺寸太大

我想使标签的文本减少到最大可能长度,而不会因为面板中的其他小部件而超过最小宽度。我已经找到了QFontMetrics::elideText()方法,它可以有效地按照我想要的方式剪裁文本,但我仍然不知道如何在标签不影响面板大小的情况下获得像素宽度

我的hackjob思想过程是通过覆盖size/minimumsize/maximumsize将Qlabel的大小设置为零,测量分配的剩余空间,然后将文本设置为零。然而,我不知道如何获得剩余的空间,我觉得应该有更好的方法

我的布局供参考:

my layout - label in question is the comically long path


Tags: 文件方法文本路径面板宽度部件尺寸
2条回答

您可以重写paintEvent(),并通过以下方式实现它:

class QElidedLabel(QLabel):
    def paintEvent(self, event):
        painter = QPainter(self)
        textDoc = QTextDocument()
        metrics = QFontMetrics(self.font())
        elided = metrics.elidedText(self.text(), Qt.ElideRight, self.width() - 10)
        textDoc.setPlainText(elided)
        textDoc.drawContents(painter)

这将自动绘制Elided标签,您无需在其他任何地方更改代码。您还可以将QLabel的大小策略设置为MinimumExpanding,以确保QLabel占用最大可用空间。这样self.width()返回当前最大宽度。您可以查看有关QTextDocument()QFontMetrics()工作的文档。另外,self.width() - 10只需确保省略标签中的'...'不被隐藏,您可以删除- 10,如果删除后..对您可见,只需使用self.width()

QLabel是一个非常简洁的小部件:它看起来非常简单,但实际上并非如此

大小和显示方面非常重要:因为它能够显示格式化文本,所以它甚至可以有一些layout issues

因为您的要求是尽可能地保持标签(但是如果可能的话保持其内容显示),最重要的要求是实现^ {CD1>}(和^ {CD2>})函数,因为父控件的布局将在调整内容的大小时考虑。p>

可能的解决方案基于两个方面:

  • 提供一个基本的[最小]大小提示,不考虑整个内容
  • 当可用空间不足时,通过删除文本覆盖绘画

下面的代码显然是<强>不/强>考虑富文本格式,包括不同的段落对齐、字包装等。

这是一个显示子类QLabel试图显示以下路径的示例: '/tmp/test_dir/some_long_path/some_subdir/imagepath/'

screenshot of elided label

<>考虑你甚至可以使用一个基本的QWIDGET。在下面的代码中,我正在考虑QFrame子类化功能,它还包括根据样式和frameShapeframeShadow属性添加适当的边距和边框

class ElideLabel(QtWidgets.QLabel):
    _elideMode = QtCore.Qt.ElideMiddle

    def elideMode(self):
        return self._elideMode

    def setElideMode(self, mode):
        if self._elideMode != mode and mode != QtCore.Qt.ElideNone:
            self._elideMode = mode
            self.updateGeometry()

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

    def sizeHint(self):
        hint = self.fontMetrics().boundingRect(self.text()).size()
        l, t, r, b = self.getContentsMargins()
        margin = self.margin() * 2
        return QtCore.QSize(
            min(100, hint.width()) + l + r + margin, 
            min(self.fontMetrics().height(), hint.height()) + t + b + margin
        )

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        opt = QtWidgets.QStyleOptionFrame()
        self.initStyleOption(opt)
        self.style().drawControl(
            QtWidgets.QStyle.CE_ShapedFrame, opt, qp, self)
        l, t, r, b = self.getContentsMargins()
        margin = self.margin()
        try:
            # since Qt >= 5.11
            m = self.fontMetrics().horizontalAdvance('x') / 2 - margin
        except:
            m = self.fontMetrics().width('x') / 2 - margin
        r = self.contentsRect().adjusted(
            margin + m,  margin, -(margin + m), -margin)
        qp.drawText(r, self.alignment(), 
            self.fontMetrics().elidedText(
                self.text(), self.elideMode(), r.width()))

相关问题 更多 >