Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在QThread中使用计时器_Python_Python 3.x_Pyqt_Pyqt5_Qtimer - Fatal编程技术网

Python 在QThread中使用计时器

Python 在QThread中使用计时器,python,python-3.x,pyqt,pyqt5,qtimer,Python,Python 3.x,Pyqt,Pyqt5,Qtimer,我有这样一个错误: QObject::startTimer: Timers can only be used with threads started with QThread 我的全部代码: from PyQt5.QtWidgets import * from newCode import mp3Download from PyQt5.QtCore import QTimer,QThread from threading import Thread import sys class Li

我有这样一个错误:

QObject::startTimer: Timers can only be used with threads started with QThread
我的全部代码:

from PyQt5.QtWidgets import *
from newCode import mp3Download
from PyQt5.QtCore import QTimer,QThread
from threading import Thread
import sys


class ListDownload(QWidget):
    def __init__(self,path):
        super().__init__()
        self.path = path
        self.time = 100
        self.initUI()
    def initUI(self):
        self.VerticalLayout = QVBoxLayout()

        self.SeasonOfWitch = QLabel()
        self.SeasonOfWitch.setText("Enter the URLs : ")

        self.URLs = QTextEdit()
        self.URLs.setText("""enter the addresses in the here .a row for each url.
        Delete this message before entering the URLs.""")

        self.horizontalControlLayout = QHBoxLayout()
        self.download = QPushButton("Download")
        self.download.clicked.connect(self.videoDownload)

        self.Cancel = QPushButton("Cancel")
        self.Cancel.clicked.connect(self.cancelFunc)
        self.horizontalControlLayout.addWidget(self.download)
        self.horizontalControlLayout.addWidget(self.Cancel)


        self.VerticalLayout.addWidget(self.SeasonOfWitch)
        self.VerticalLayout.addWidget(self.URLs)
        self.VerticalLayout.addLayout(self.horizontalControlLayout)

        self.setLayout(self.VerticalLayout)        

    def cancelFunc(self):
        self.close()

    def videoDownload(self):
        self.urlList = self.URLs.toPlainText().split("\n")
        row = 1
        errorList = list()
        for url in self.urlList:
            if 'www.youtube.com' in url.split("/") and (url.startswith("https://") or url.startswith("http://")):
                row+=1

            else:
                errorList.append(row)
                row+=1

        decrease = 0#Each element deleting index changes the lenght of the list.Cause of that.
        for row in errorList:
            self.urlList.pop(row-1-decrease)
            decrease += 1

        messageObj = Thread(target=self.messageAnimation,name="message")
        downloadObj = Thread(target=self.downloadFunc,name="download")


        messageObj.start()
        downloadObj.start()

        while not(downloadObj.is_alive()):
            messageObj._stop()

    def downloadFunc(self):
        mp3Download(self.urlList,self.path)

    def messageAnimation(self):
        def timerFunc():
            self.animatedMessageFunc("Downloading ....")

        self.timer = QTimer()
        self.timer.timeout.connect(timerFunc)
        self.timer.start(1000)    


    def remove_widget(self,layout,widget_name):
        layout.removeWidget(widget_name)
        widget_name.deleteLater()
        widget_name = None

    def animatedMessageFunc(self,message):
        animatedMessage = message
        self.URLs.clear()
        iterator = iter(range(len(animatedMessage)))
        for i in range(len(animatedMessage)):
            QTimer.singleShot(self.time,lambda :self.URLs.setText(self.URLs.toPlainText()+animatedMessage[next(iterator)]))
            self.time += 50
        self.time = 100
问题是计时器。在
animatedMessageFunc()
中。我想启动两个函数 同时,我使用
threading
模块中的
Thread
类。我想要它是因为
self.downloadFunc()
结束时,我需要停止
self.messageAnimation()
函数。我尝试使用QThread代替Thread。但是我不知道该如何使用这个类。有一些错误和我的一样。但是这些错误在java或其他语言中。我找不到解决这些问题的方法。

计时器不必在另一个线程中,只要在线程启动时启动,在线程结束任务时停止,就足够了,为此,我们创建了两个信号:
started
finished
,分别在调用
mp3Download()
函数前后发出

import sys
from itertools import cycle
from threading import Thread
from PyQt5 import QtCore, QtGui, QtWidgets

from newCode import mp3Download


class ListDownload(QtWidgets.QWidget):
    started = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal()

    def __init__(self, path):
        super().__init__()
        self.path = path
        self.initUI()

    def initUI(self):
        VerticalLayout = QtWidgets.QVBoxLayout(self)

        SeasonOfWitch = QtWidgets.QLabel("Enter the URLs : ")

        self.URLs = QtWidgets.QTextEdit()
        self.URLs.setText("""enter the addresses in the here .a row for each url.
        Delete this message before entering the URLs.""")

        horizontalControlLayout = QtWidgets.QHBoxLayout()
        download = QtWidgets.QPushButton("Download")
        download.clicked.connect(self.videoDownload)

        Cancel = QtWidgets.QPushButton("Cancel")
        Cancel.clicked.connect(self.close)
        horizontalControlLayout.addWidget(download)
        horizontalControlLayout.addWidget(Cancel)

        VerticalLayout.addWidget(SeasonOfWitch)
        VerticalLayout.addWidget(self.URLs)
        VerticalLayout.addLayout(horizontalControlLayout)

        self.started.connect(self.messageAnimation)

    def videoDownload(self):
        lines = self.URLs.toPlainText().split("\n")
        urls = []
        for line in lines:
            if 'www.youtube.com' in line.split("/") and (line.startswith("https://") or line.startswith("http://")):
                urls.append(line)
        if urls:
            Thread(target=self.downloadFunc, args=(urls,), name="download", daemon=True).start()

    def downloadFunc(self, urls):
        self.started.emit()
        mp3Download(urls, self.path)
        self.finished.emit()

    def messageAnimation(self):
        self.URLs.clear()
        text = "Downloading ...."
        timer = QtCore.QTimer(self, interval=50)
        it = cycle(text+"\n")
        timer.timeout.connect(lambda: self.appendLetter(next(it)))
        timer.start()
        self.finished.connect(timer.stop)
        self.finished.connect(self.URLs.clear)

    def appendLetter(self, letter):
        if letter == "\n":
            self.URLs.clear()
        else:
            self.URLs.moveCursor(QtGui.QTextCursor.End)
            self.URLs.insertPlainText(letter)
            self.URLs.moveCursor(QtGui.QTextCursor.End)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    path = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DownloadLocation)
    w = ListDownload(path)
    w.show()
    sys.exit(app.exec_())

计时器不必在另一个线程中,只要在线程启动时启动,在线程结束任务时停止就足够了,为此我们创建了两个信号:
started
finished
,分别在调用
mp3Download()
函数之前和之后发出

import sys
from itertools import cycle
from threading import Thread
from PyQt5 import QtCore, QtGui, QtWidgets

from newCode import mp3Download


class ListDownload(QtWidgets.QWidget):
    started = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal()

    def __init__(self, path):
        super().__init__()
        self.path = path
        self.initUI()

    def initUI(self):
        VerticalLayout = QtWidgets.QVBoxLayout(self)

        SeasonOfWitch = QtWidgets.QLabel("Enter the URLs : ")

        self.URLs = QtWidgets.QTextEdit()
        self.URLs.setText("""enter the addresses in the here .a row for each url.
        Delete this message before entering the URLs.""")

        horizontalControlLayout = QtWidgets.QHBoxLayout()
        download = QtWidgets.QPushButton("Download")
        download.clicked.connect(self.videoDownload)

        Cancel = QtWidgets.QPushButton("Cancel")
        Cancel.clicked.connect(self.close)
        horizontalControlLayout.addWidget(download)
        horizontalControlLayout.addWidget(Cancel)

        VerticalLayout.addWidget(SeasonOfWitch)
        VerticalLayout.addWidget(self.URLs)
        VerticalLayout.addLayout(horizontalControlLayout)

        self.started.connect(self.messageAnimation)

    def videoDownload(self):
        lines = self.URLs.toPlainText().split("\n")
        urls = []
        for line in lines:
            if 'www.youtube.com' in line.split("/") and (line.startswith("https://") or line.startswith("http://")):
                urls.append(line)
        if urls:
            Thread(target=self.downloadFunc, args=(urls,), name="download", daemon=True).start()

    def downloadFunc(self, urls):
        self.started.emit()
        mp3Download(urls, self.path)
        self.finished.emit()

    def messageAnimation(self):
        self.URLs.clear()
        text = "Downloading ...."
        timer = QtCore.QTimer(self, interval=50)
        it = cycle(text+"\n")
        timer.timeout.connect(lambda: self.appendLetter(next(it)))
        timer.start()
        self.finished.connect(timer.stop)
        self.finished.connect(self.URLs.clear)

    def appendLetter(self, letter):
        if letter == "\n":
            self.URLs.clear()
        else:
            self.URLs.moveCursor(QtGui.QTextCursor.End)
            self.URLs.insertPlainText(letter)
            self.URLs.moveCursor(QtGui.QTextCursor.End)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    path = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DownloadLocation)
    w = ListDownload(path)
    w.show()
    sys.exit(app.exec_())