【问题标题】:How to scroll text in QTextEdit automatically (animational effect)?如何在 QTextEdit 中自动滚动文本(动画效果)?
【发布时间】:2020-01-22 08:12:26
【问题描述】:

请问如何在QTextEdit scoll中制作文字,达到动画效果。动画效果应该和视频中的一样: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_())

非常感谢您的帮助!

【问题讨论】:

  • @eyllanesc 我粘贴视频只是为了表示。它显示文本已自动向上“移动”或“缩放”。在视频中,文本来自底部,但在我的情况下,文本可以从顶部开始。正如我所说,视频只是一个代表。我在上面编辑了我的问题,现在可以理解了吗?
  • @eyllanesc 单击按钮时,会加载文本,并开始自动滚动。一切都应该是自动的。只需单击一下,其余所有自动运行。
  • @eyllanesc 我不想下载视频。视频仅作展示,仅此而已。我只想让文本自动滚动。是你不懂我吗?
  • @eyllanesc 现在我明白你的意思了。我想在开头(单击按钮时)加载全文,但一点一点地显示文本。
  • @eyllanesc 是的,点击按钮时加载所有文本,然后自动开始自动滚动。

标签: python pyqt pyqt5 qtextedit


【解决方案1】:

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

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

对于最后一个,我们必须开始移动到最后一个可见的初始值,我们使用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_())

更新:

如果你想连续移动,你必须使用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_())

【讨论】:

  • 太棒了!太感谢了!你的想法和我的很不一样。它可以工作,但我必须了解更多才能了解它是如何工作的。 :-)
  • 嗨@eyllanesc,我可以问你一些提示,使文本滚动顺畅吗?上面的方法逐行移动文本。有什么方法可以逐个像素地滚动文本吗?谢谢。
  • 谢谢!取消选中答案是我做错了。很抱歉。
猜你喜欢
  • 2020-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多