【问题标题】:Smooth scrolling text in QlabelQlabel 中的平滑滚动文本
【发布时间】:2016-07-17 18:48:16
【问题描述】:

我正在尝试使用 Qlabel 作为消息中心,将消息中继给应用程序的用户。有些消息可能比 Qlabel 允许的长,我希望它水平滚动直到文本结束。如何在 Qlabel 中执行此操作?我似乎在设计器中找不到任何东西,也不想在代码中找出某种截断方法,只从字符串的前面截断,这似乎很愚蠢。

【问题讨论】:

  • 你想让它自动滚动,就像那些发光的标志之一?或者您只是希望用户能够滚动它?
  • 发光标志。确实。不希望任何人能够移动它。

标签: python-2.7 pyqt pyqt4 qwidget qlabel


【解决方案1】:

您所追求的通常称为 Marquee 小部件。这是一个使用QLabel 的非常简单且生锈的实现,但也可以使用QWidget 来完成。我重写了使用QTextDocument 的setText 方法,其父对象是QLabel 本身,它包含文本。如果文本大于QLabel 的大小,则QTimer 会触发移动文本的翻译方法:

import sys

from PyQt5.QtCore import QEvent, QTimer, pyqtSlot
from PyQt5.QtGui import QTextDocument, QPainter, QFontMetrics
from PyQt5.QtWidgets import QLabel, QApplication


class Marquee(QLabel):

    x = 0

    paused = False
    document = None
    speed = 50
    timer = None

    def __init__(self, parent=None):
        super().__init__(parent)
        self.fm = QFontMetrics(self.font())
        self.setFixedSize(200, 20)

    def setText(self, value):
        self.x = 0

        self.document = QTextDocument(self)
        self.document.setPlainText(value)
        # I multiplied by 1.06 because otherwise the text goes on 2 lines
        self.document.setTextWidth(self.fm.width(value) * 1.06)
        self.document.setUseDesignMetrics(True)

        if self.document.textWidth() > self.width():
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.translate)
            self.timer.start((1 / self.speed) * 1000)

    @pyqtSlot()
    def translate(self):
        if not self.paused:
            if self.width() - self.x < self.document.textWidth():
                self.x -= 1
            else:
                self.timer.stop()
        self.repaint()

    def event(self, event):
        if event.type() == QEvent.Enter:
            self.paused = True
        elif event.type() == QEvent.Leave:
            self.paused = False
        return super().event(event)

    def paintEvent(self, event):
        if self.document:
            p = QPainter(self)
            p.translate(self.x, 0)
            self.document.drawContents(p)
        return super().paintEvent(event)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    w = Marquee()
    w.setText('Lorem ipsum dolor sit amet, consectetur adipiscing elit...')
    w.show()
    sys.exit(app.exec_())

【讨论】:

    【解决方案2】:

    Qt 中没有默认情况下执行此操作。您确实需要创建一个更改文本的动画。

    您可以使用QFontMetrics (label.fontMetrics()) 来确定标签文本是否大于QLabel(以了解是否需要滚动)。您需要一种方法来每半秒左右重新绘制一次QLabel,以便为滚动设置动画。最简单的方法可能是QTimer。最简单的方法可能是继承QLabel 并让它检查它是否需要自行滚动并每隔半秒左右重置一次文本以模拟滚动。

    如果您希望滚动更流畅(在子字符级别),您必须覆盖绘制方法并自己绘制文本并根据需要对其进行翻译和剪辑。

    【讨论】:

    • 这听起来就像我真正想要避免的。谢谢,我只是想办法巧妙地限制允许的文本大小。
    • Qlabels 让你知道自动换行。
    • 是的,但我们希望在相当小的空间内使用大字体,不要认为自动换行会起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    相关资源
    最近更新 更多