如何在QThread和某些子类之间“通信”?

2024-06-17 09:49:04 发布

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

对于这个问题,我指的是@eyllanesc在PyQt5: How to scroll text in QTextEdit automatically (animational effect)?中给出的答案

在这里@eyllanesc演示了如何使用verticalScrollBar()使文本自动滚动。效果很好。

对于这个问题,我添加了一些额外的行,用QThread来获取文本。

我想实现的是:QThread classAnimationTextEdit class通信,这样滚动时间就可以由文本长度决定了。当滚动过程结束时,程序停止。

我必须说,这对我来说是非常棘手的任务。我想先展示程序流程,就像我想象的那样。

enter image description here

更新:我的代码如下。它很管用,但是。。。

代码问题:当文本停止滚动时,time.sleep()仍然有效。应用程序在那里等待time.sleep()停止。

我想得到的是:当文本停止滚动时,time.sleep()将运行到其结束值。

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import time
import sqlite3


class AnimationTextEdit(QTextEdit):
    # signal_HowLongIsTheText = pyqtSignal(int)  # signal to tell the QThread, how long the text is

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

    # def sent_Info_to_Thread(self):
    #     self.obj_Thread = Worker()
    #     self.signal_HowLongIsTheText.connect(self.obj_Thread.getText_HowLongIsIt)
    #     self.signal_HowLongIsTheText.emit(self.textLength)
    #     self.signal_HowLongIsTheText.disconnect(self.obj_Thread.getText_HowLongIsIt)


    @pyqtSlot()
    def startAnimation(self):
        self.animation.stop()
        self.animation.setStartValue(0)

        self.textLength = self.verticalScrollBar().maximum()
        # self.sent_Info_to_Thread()


        self.animation.setEndValue(self.textLength)
        self.animation.setDuration(self.animation.endValue()*4)
        self.animation.start()

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



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

    # @pyqtSlot(int)
    # def getText_HowLongIsIt(self, textLength):
    #     self.textLength = textLength

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

        self.textSignal.emit(longText)

        time.sleep(10)
        # time.sleep(int(self.textLength / 100))
        # My question is about the above line: time.sleep(self.textLength)
        # Instead of giving a fixed sleep time value here,
        # I want let the Worker Class know,
        # how long it will take to scroll all the text to the end.

        self.finished.emit()


class MyApp(QWidget):
    def __init__(self):
        super(MyApp, self).__init__()
        self.setFixedSize(600, 400)
        self.initUI()
        self.startThread()

    def initUI(self):
        self.txt = AnimationTextEdit(self)
        self.btn = QPushButton("Start", self)

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

        self.btn.clicked.connect(self.txt.startAnimation)

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

        self.obj.textSignal.connect(self.textUpdate)
        self.obj.moveToThread(self.thread)
        self.obj.finished.connect(self.thread.quit)
        self.thread.started.connect(self.obj.getText)
        self.thread.finished.connect(app.exit)
        self.thread.start()

    def textUpdate(self, longText):
        self.txt.append(longText)
        self.txt.moveToLine(0)


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

谢谢你的帮助和暗示。我做错了什么?


Tags: theto文本importselfobjsignaltime
1条回答
网友
1楼 · 发布于 2024-06-17 09:49:04

虽然在动画中确定了持续时间,但有必要了解这并不准确,但这可能会因多种原因而变化,因此使用睡眠来等待它在某个时间内结束并关闭应用程序可能会失败。在

如果您的主要目标是当动画完成时程序执行结束,那么您必须使用finished QVariantAnimation信号来完成线程的执行,该信号在它完成执行时发出。在

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.textLength = self.verticalScrollBar().maximum()
        self.animation.setEndValue(self.textLength)
        self.animation.setDuration(self.animation.endValue()*4)
        self.animation.start()

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


class Worker(QObject):
    textSignal = pyqtSignal(str)
    @pyqtSlot()
    def getText(self):
        longText = "\n".join(["{}: long text - auto scrolling ".format(i) for i in range(100)])
        self.textSignal.emit(longText)


class MyApp(QWidget):
    def __init__(self):
        super(MyApp, self).__init__()
        self.setFixedSize(600, 400)
        self.initUI()
        self.startThread()

    def initUI(self):
        self.txt = AnimationTextEdit(self)
        self.btn = QPushButton("Start", self)

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

        self.btn.clicked.connect(self.txt.startAnimation)

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

        self.obj.textSignal.connect(self.textUpdate)
        self.obj.moveToThread(self.thread)
        self.txt.animation.finished.connect(self.thread.quit)
        self.thread.started.connect(self.obj.getText)
        self.thread.finished.connect(app.exit)
        self.thread.start()

    def textUpdate(self, longText):
        self.txt.append(longText)
        self.txt.moveToLine(0)


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

相关问题 更多 >