在 QThread 中使用定时器
Using Timers with QThread
我遇到了这样的错误:
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()
。我想启动两个功能
在同一个 time.I 中使用 threading
模块中的 Thread
class。我想要它是因为
当 self.downloadFunc()
结束时,我需要停止 self.messageAnimation()
函数。我尝试使用 QThread 而不是 Thread。但我无法弄清楚如何使用此 class.There 是错误,因为 mine.But java 或其他一些 language.I 中的错误无法找到我的解决方案问题。
计时器不必在另一个线程中,当线程启动时启动并在线程结束其任务时停止它就足够了,为此我们创建了 2 个信号: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_())
我遇到了这样的错误:
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()
。我想启动两个功能
在同一个 time.I 中使用 threading
模块中的 Thread
class。我想要它是因为
当 self.downloadFunc()
结束时,我需要停止 self.messageAnimation()
函数。我尝试使用 QThread 而不是 Thread。但我无法弄清楚如何使用此 class.There 是错误,因为 mine.But java 或其他一些 language.I 中的错误无法找到我的解决方案问题。
计时器不必在另一个线程中,当线程启动时启动并在线程结束其任务时停止它就足够了,为此我们创建了 2 个信号: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_())