¿Cómo conectar una barra de progreso utilizando QThread en PyQT5? [Python 3x]

Iniciado por erickcasita, 15 Abril 2019, 17:03 PM

0 Miembros y 1 Visitante están viendo este tema.

erickcasita

He estado intentado pasar el proceso de descarga para los audios de Youtube en un hilo diferente utilizando la librería pafy. Con esta librería se puede utilizar un método llamado "mycb" donde es posible obtener los kbs descargados y los totales para establecer una barra de progreso. Aquí les muestro lo que intento hacer mediante la clase QThread

Código (python) [Seleccionar]


from audio import *
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog,QFileDialog, QMessageBox,QTableWidget,QTableWidgetItem
from PyQt5.QtCore import QThread, pyqtSignal
import getpass, glob, pafy

class DownloadAudio(QThread):
    signal_recvd = pyqtSignal(int)
    signal_total = pyqtSignal(int)
    def download(self, ruta, url):
        ruta = ruta
        url = url
        video = pafy.new(url)
        title = video.title
        duration = video.duration
        dwn = video.getbestaudio()
        dwn.download(filepath=ruta, callback=self.mycb, meta=True)

    def mycb(self,total, recvd, ratio, rate,eta): #Metodo de la libreria Pafy para saber los kbs recibidos y los totales (con este me apoyo para establecer la barra de progreso)
        self.signal_total.emit(total)
        self.signal_recvd.emit(recvd)


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        QtWidgets.QMainWindow.__init__(self, *args, **kwargs)
        self.setupUi(self)
        self.setFixedSize(920,700)
        self.txt_ruta.setText("/home/"+getpass.getuser()+"/Música")
        self.tableWidget.setColumnWidth(0, 350)
        self.tableWidget.setColumnWidth(1, 350)
        self.btn_descargar.clicked.connect(self.download_audio)
        self.btn_destino.clicked.connect(self.ruta)
    def download_audio(self):
        ruta = self.txt_ruta.text()
        self.progressBar.setValue(0)
        url = self.txt_url.text()
        video = pafy.new(url)
        title = video.title
        duration = video.duration
        self.tableWidget.setItem(0,0, QTableWidgetItem(title))
        self.tableWidget.setItem(0,1, QTableWidgetItem(duration))
        self.calc = DownloadAudio()
        self.calc.download(ruta,url)
        self.calc.signal_recvd.connect(self.progress)
    def progress(self,value):
        self.progressBar.setValue(value)

    def ruta(self):
        path = os.path.normpath(QFileDialog.getExistingDirectory(self))
        self.txt_ruta.setText(path)                 
if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    window = MainWindow()
    window.show()
    app.exec_()




Con este código el proceso funciona aunque no correctamente ni mucho menos puedo establecer la barra de progreso.
"Nadie nace sabiendo, Todos aprendemos y seguimos aprendiendo."

srWhiteSkull

No tengo tiempo para instalar Qt pero así por encima veo que defines una clase que hereda de un objeto QThread que por el nombre alude a un "hilo", un proceso que funciona en segundo plano.

https://www.riverbankcomputing.com/static/Docs/PyQt4/qthread.html

Viendo la documentación observo que QThread dispone de un método donde corre el hilo, el run. En teoría tal como indica la doc este me´todo indica que todo lo que metas ahí lo ejecuta en segundo plano. Por lo tanto necesitas incluir en esa clase que defines el método run que lo heredará de QThread.

Luego en el run debes poner un bucle condicional que termine cuando de alguna forma, tú sabrás, el fichero haya llegado al total o fuese descargado y entonces el bucle finalizaría. Dentro de ese mismo bucle es donde tendrías que actualizar la barra de progreso.

Una vez tengas todo eso, ya simplemente cuando instancies la clase DownloadAudio deberías invocar el método start. Y así debería funcionar, pero me imagino que deberías pasar la referencia de la barra de progreso.

Otra alternativa a ese diseño pienso que sería que ya que esa función mycb que defines te devuelve el tamaño, sería conveniente que el hilo lo ejecutara el componente de barra de progreso, y este mientras se ejecuta en segundo plano se vaya actualizando en cada vuelta del bucle en el run, consultando periódicamente esa función, mycb,y claro, que también tendrías que pasarle la referencia del DownloadAudio instanciado.

erickcasita

Gracias por el algoritmo hermano, así mismo lo voy a intentar, saludos!
"Nadie nace sabiendo, Todos aprendemos y seguimos aprendiendo."