如何在QTextEdit中自动滚动文本(动画效果)?

2024-04-28

我想问一下如何让QTextEdit中的文字滚动,达到动画效果。动画效果应该类似于视频中所示的效果:https://www.youtube.com/watch?v=MyeuGdXv4XM https://www.youtube.com/watch?v=MyeuGdXv4XM

使用 PyQt 我想得到这样的效果: 文本应以 2 行/秒的速度自动向下滚动,直到到达末尾并停止。

在下面的代码中,当单击按钮时,文本将显示在 QTextEdit-Widget 中。文字很长,所以会出现滚动条。

我的问题: 我不知道如何制作动画效果。因此我想请求您帮助纠正我的代码。

# -*- coding: utf-8 -*-

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

import sys
import time


list_longText = [" long text 1 - auto scrolling " * 1000, " long text 2 - auto scrolling " * 2000]

class Worker(QObject):
    finished = pyqtSignal()
    strTxt = pyqtSignal(str)

    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)

    @pyqtSlot()
    def onJob(self):
        for i in range(2):
            self.strTxt.emit(list_longText[i])
            time.sleep(2)

class MyApp(QWidget):
    def __init__(self):
        super(MyApp, self).__init__()
        self.setFixedSize(600, 400)
        self.setObjectName("window")

        self.initUI()


    def initUI(self):

        self.txt = QTextEdit("", self)
        self.btn = QPushButton("Button", self)
        self.btn.clicked.connect(self.start)

        self.layout = QHBoxLayout(self)
        self.layout.addWidget(self.txt)
        self.layout.addWidget(self.btn)
        self.setLayout(self.layout)

        self.show()

    def start(self):
        self.thread = QThread()
        self.obj = Worker()

        self.obj.strTxt.connect(self.showText)
        self.obj.moveToThread(self.thread)
        self.obj.finished.connect(self.thread.quit)
        self.thread.started.connect(self.obj.onJob)
        self.thread.start()

    def showText(self, str):
        self.txt.setText("{}".format(str))
        self.autoScroll()

    def autoScroll(self):
        vsb = self.txt.verticalScrollBar()
        if vsb.value() <= vsb.maximum():
            vsb.setValue(vsb.value() + 2)
            time.sleep(1)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyApp()
    sys.exit(app.exec_())

非常感谢您的帮助!


你想要的任务并不繁重,它是周期性的,所以使用线程是不合适的,对于这个任务我们可以使用QVariantAnimation.

另一部分是创建一个移动到我们使用的特定文本行的方法QTextCursor旁边findBlockByLineNumber() of QTextDocument.

对于最后一个,我们必须开始移动到最后一个可见的初始字母,因为我们使用cursorForPosition()方法通过大小viewport().

longText = "\n".join(["{}: long text - auto scrolling ".format(i) for i in range(100)])

class AnimationTextEdit(QTextEdit):
    def __init__(self, *args, **kwargs):
        QTextEdit.__init__(self, *args, **kwargs)
        self.animation = QVariantAnimation(self)
        self.animation.valueChanged.connect(self.move)

    @pyqtSlot()
    def startAnimation(self):
        self.animation.stop()
        lines_per_second = 2
        self.moveToLine(0)
        p = QPoint(self.viewport().width() - 1, self.viewport().height() - 1)
        cursor = self.cursorForPosition(p)
        self.animation.setStartValue(cursor.blockNumber())
        self.animation.setEndValue(self.document().blockCount()-1)
        self.animation.setDuration(self.animation.endValue()*1000/lines_per_second)
        self.animation.start()

    @pyqtSlot(QVariant)
    def move(self, i):
        cursor = QTextCursor(self.document().findBlockByLineNumber(i))
        self.setTextCursor(cursor)

class MyApp(QWidget):
    def __init__(self):
        super(MyApp, self).__init__()
        self.setFixedSize(600, 400)
        self.txt = AnimationTextEdit(self)
        self.btn = QPushButton("Start", self)
        self.layout = QHBoxLayout(self)
        self.layout.addWidget(self.txt)
        self.layout.addWidget(self.btn)
        self.txt.append(longText)
        self.txt.move(0)
        self.btn.clicked.connect(self.txt.startAnimation)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

Update:

如果你想要连续运动,你必须使用verticalScrollBar():

longText = "\n".join(["{}: long text - auto scrolling ".format(i) for i in range(100)])

class AnimationTextEdit(QTextEdit):
    def __init__(self, *args, **kwargs):
        QTextEdit.__init__(self, *args, **kwargs)
        self.animation = QVariantAnimation(self)
        self.animation.valueChanged.connect(self.moveToLine)

    @pyqtSlot()
    def startAnimation(self):
        self.animation.stop()
        self.animation.setStartValue(0)
        self.animation.setEndValue(self.verticalScrollBar().maximum())
        self.animation.setDuration(self.animation.endValue()*4)
        self.animation.start()

    @pyqtSlot(QVariant)
    def moveToLine(self, i):
        self.verticalScrollBar().setValue(i)

class MyApp(QWidget):
    def __init__(self):
        super(MyApp, self).__init__()
        self.setFixedSize(600, 400)
        self.txt = AnimationTextEdit(self)
        self.btn = QPushButton("Start", self)
        self.layout = QHBoxLayout(self)
        self.layout.addWidget(self.txt)
        self.layout.addWidget(self.btn)
        self.txt.append(longText)
        self.txt.moveToLine(0)
        self.btn.clicked.connect(self.txt.startAnimation)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在QTextEdit中自动滚动文本(动画效果)? 的相关文章

随机推荐