转移到另一个线程的一种方法是创建一个
QObject驻留在另一个线程中的线程,并在插槽中执行该任务。并且该插槽必须通过
QmetaObject::invokeMethod或信号来调用。
with QThread and QmetaObject::invokeMethod:
import pafyfrom PyQt5 import QtCore, QtWidgetsclass MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) central_widget = QtWidgets.QWidget() self.setCentralWidget(central_widget) self.le_url = QtWidgets.QLineEdit("https://www.youtube.com/watch?v=bMt47wvK6u0") path = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DownloadLocation) self.le_output = QtWidgets.QLineEdit(path) self.btn_quality = QtWidgets.QPushButton("Get qualities") self.combo_quality = QtWidgets.QComboBox() self.btn_download = QtWidgets.QPushButton("Download") self.progressbar = QtWidgets.QProgressBar(maximum=100) self.downloader = DownLoader() thread = QtCore.QThread(self) thread.start() self.downloader.moveToThread(thread) self.btn_quality.clicked.connect(self.on_clicked_quality) self.btn_download.clicked.connect(self.download) self.btn_download.setDisabled(True) self.downloader.progressChanged.connect(self.progressbar.setValue) self.downloader.qualitiesChanged.connect(self.update_qualityes) self.downloader.finished.connect(self.on_finished) form_lay = QtWidgets.QFormLayout(central_widget) form_lay.addRow("Url: ", self.le_url) form_lay.addRow(self.btn_quality) form_lay.addRow("qualities: ", self.combo_quality) form_lay.addRow("Output: ", self.le_output) form_lay.addRow(self.btn_download) form_lay.addRow(self.progressbar) @QtCore.pyqtSlot() def on_finished(self): self.update_disables(False) @QtCore.pyqtSlot() def on_clicked_quality(self): video_url = self.le_url.text() QtCore.QmetaObject.invokeMethod(self.downloader, "get_qualities", QtCore.Qt.QueuedConnection, QtCore.Q_ARG(str, video_url)) @QtCore.pyqtSlot(list) def update_qualityes(self, types_of_video): for t in types_of_video: self.combo_quality.addItem(str(t), t) self.btn_download.setDisabled(False) @QtCore.pyqtSlot() def download(self): video_save = self.le_output.text() d = self.combo_quality.currentData() QtCore.QmetaObject.invokeMethod(self.downloader, "start_download", QtCore.Qt.QueuedConnection, QtCore.Q_ARG(object, d), QtCore.Q_ARG(str, video_save)) self.update_disables(True) def update_disables(self, state): self.combo_quality.setDisabled(state) self.btn_quality.setDisabled(state) self.le_output.setDisabled(state) self.le_url.setDisabled(state) self.btn_download.setDisabled(not state)class DownLoader(QtCore.QObject): progressChanged = QtCore.pyqtSignal(int) qualitiesChanged = QtCore.pyqtSignal(list) finished = QtCore.pyqtSignal() @QtCore.pyqtSlot(str) def get_qualities(self, video_url): pafy_video = pafy.new(video_url) types_of_video = pafy_video.allstreams # videostreams self.qualitiesChanged.emit(types_of_video) @QtCore.pyqtSlot(object, str) def start_download(self, d, filepath): d.download(filepath=filepath, callback=self.callback) def callback(self, total, recvd, ratio, rate, eta): val = int(ratio * 100) self.progressChanged.emit(val) if val == 100: self.finished.emit()if __name__ == '__main__': import sys app = QtWidgets.QApplication(sys.argv) w = MainWindow() w.resize(320, 480) w.show() sys.exit(app.exec_())
with threading.Thread:
import pafyimport threadingfrom PyQt5 import QtCore, QtWidgetsclass MainWindow(QtWidgets.QMainWindow): qualitiesChanged = QtCore.pyqtSignal(list) progressChanged = QtCore.pyqtSignal(int) finished = QtCore.pyqtSignal() def __init__(self, parent=None): super(MainWindow, self).__init__(parent) central_widget = QtWidgets.QWidget() self.setCentralWidget(central_widget) self.le_url = QtWidgets.QLineEdit("https://www.youtube.com/watch?v=bMt47wvK6u0") path = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DownloadLocation) self.le_output = QtWidgets.QLineEdit(path) self.btn_quality = QtWidgets.QPushButton("Get qualities") self.combo_quality = QtWidgets.QComboBox() self.btn_download = QtWidgets.QPushButton("Download") self.progressbar = QtWidgets.QProgressBar(maximum=100) self.btn_quality.clicked.connect(self.on_clicked_quality) self.btn_download.clicked.connect(self.download) self.btn_download.setDisabled(True) self.progressChanged.connect(self.progressbar.setValue) self.qualitiesChanged.connect(self.update_qualityes) self.finished.connect(self.on_finished) form_lay = QtWidgets.QFormLayout(central_widget) form_lay.addRow("Url: ", self.le_url) form_lay.addRow(self.btn_quality) form_lay.addRow("qualities: ", self.combo_quality) form_lay.addRow("Output: ", self.le_output) form_lay.addRow(self.btn_download) form_lay.addRow(self.progressbar) @QtCore.pyqtSlot() def on_finished(self): self.update_disables(False) @QtCore.pyqtSlot() def on_clicked_quality(self): video_url = self.le_url.text() threading.Thread(target=self.get_qualities, args=(video_url,)).start() def get_qualities(self, video_url): pafy_video = pafy.new(video_url) types_of_video = pafy_video.allstreams # videostreams self.qualitiesChanged.emit(types_of_video) @QtCore.pyqtSlot(list) def update_qualityes(self, types_of_video): for t in types_of_video: self.combo_quality.addItem(str(t), t) self.btn_download.setDisabled(False) @QtCore.pyqtSlot() def download(self): video_save = self.le_output.text() d = self.combo_quality.currentData() threading.Thread(target=d.download, kwargs={'filepath': video_save, 'callback': self.callback}, daemon=True).start() def callback(self, total, recvd, ratio, rate, eta): print(ratio) val = int(ratio * 100) self.progressChanged.emit(val) if val == 100: self.finished.emit() def update_disables(self, state): self.combo_quality.setDisabled(state) self.btn_quality.setDisabled(state) self.le_output.setDisabled(state) self.le_url.setDisabled(state) self.btn_download.setDisabled(not state)if __name__ == '__main__': import sys app = QtWidgets.QApplication(sys.argv) w = MainWindow() w.resize(320, 480) w.show() sys.exit(app.exec_())
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)