Qlabel中的平滑滚动文本

问题描述:

我正在尝试使用Qlabel作为消息中心将消息转发给应用程序的用户。一些消息可能比Qlabel允许的更长,我希望它只是水平滚动直到文本结束。我怎样才能在Qlabel中做到这一点?我似乎无法在设计器中找到任何东西,也不想在代码中找到某种截断方法,只是从字符串的前面取下一些片断,看起来很愚蠢。Qlabel中的平滑滚动文本

+0

你希望它自动滚动,像那些点燃的迹象吗?或者你只是想让用户能够滚动它? –

+0

发光的迹象。当然。不希望任何人能够移动它。 – electrometro

在默认情况下,Qt并没有这样做。您确实需要创建一个改变文本的动画。

您可以使用QFontMetricslabel.fontMetrics())来确定标签文本是否大于QLabel(要知道是否需要滚动它)。您需要每半秒重新绘制一次QLabel的方法来为滚动设置动画。最简单的方法可能是QTimer。最简单的方法可能是QLabel的子类,并检查它是否需要滚动自己并每隔半秒左右重置文本以模拟滚动。

如果您希望滚动更平滑(在子字符级别),您必须重写paint方法,并根据需要自行绘制文本并进行剪裁。

+0

这听起来完全像我真正想避免的。谢谢,我只是试图找到一种方法来巧妙地限制文本的大小。 – electrometro

+0

Qlabels允许你知道wordwrap。 –

+0

是的,但我们希望在一个相当小的空间中使用大字体,不要以为换行就行。 – electrometro

你所追求的是俗称的选框部件。这是一个非常简单和生锈的实现,它使用了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_())