【问题标题】:how i can make thread for progress bar with pafy我如何用 pafy 为进度条制作线程
【发布时间】:2019-01-04 14:55:11
【问题描述】:

我正在尝试解决我的程序中的问题,这个问题是当我开始下载视频时,程序没有响应,我也看不到进度条移动,所以我尝试使用线程模块,但我无法解决问题所以我该如何解决问题

通过此代码,我可以下载视频并将数据发送到另一个函数,以检索我用来将其连接到进度条的信息

def video(self):
    video_url = self.lineEdit_4.text()
    video_save = self.lineEdit_3.text()

    pafy_video = pafy.new(video_url)
    type_video = pafy_video.videostreams

    quality = self.comboBox.currentIndex()

    start_download = type_video[quality].download(filepath=video_save,callback=self.video_progressbar)

此代码是从视频功能接收信息以连接进度条

def video_progressbar(self,total, recvd, ratio, rate, eta):
    self.progressBar_2.setValue(ratio * 100)

我用;python3.5 pyqt5 pafy

【问题讨论】:

    标签: python pyqt pyqt5 pafy


    【解决方案1】:

    移动到另一个线程的一种方法是创建一个位于另一个线程中的QObject,并在一个槽中执行该任务。并且该槽必须通过QMetaObject::invokeMethod 或信号调用。

    with QThread and QMetaObject::invokeMethod:

    import pafy
    from PyQt5 import QtCore, QtWidgets
    
    class 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 pafy
    import threading
    from PyQt5 import QtCore, QtWidgets
    
    class 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_())
    

    【讨论】:

    • 感谢您的代码运行良好,但我的代码无法使用 qthread,我使用的是 QmainWindow
    • 因为我理解你是50%的代码所以我尝试使用qthread,并没有成功解决无响应问题
    • 你刚换了课
    • 我会把我的代码交给你解决我的问题,并将 qthread 放在正确的位置
    • 谢谢你,我再次尝试阅读你的代码,我现在明白了如何使用线程
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    相关资源
    最近更新 更多