Revsky01
Revsky01

Reputation: 225

QProgressBar does not show copy progress

I am creating an application that shows the progress of copying a file, the copying process works perfectly the problem is that the QProgressBar is not updated with the appropriate value

The copy () function of the Copy Thread class is responsible for realizing the process of copying theSrc_School_Admin folder along with the files within it to the new directory created in this case the SchoolAdministration folder.

To update the value of the QProgressBar I execute a cycle that updates the size value of the target directory once the destination directorySchoolAdministration has the same weight as Src_School_Admin, then the cycle is broken.

The self.procPartDone signal receives as an argument an operation to calculate the percentage that issize_original_folder * 100 / target_folder_size.

However, the value of the QProgressBar is not updated, I hope you can help me

File.py

from PyQt5.QtWidgets import QMainWindow,QApplication,QMessageBox
from PyQt5 import uic,QtCore
import shutil,os
import platform
import threading

class CopyThread(QtCore.QThread):
    procDone = QtCore.pyqtSignal(bool)
    procPartDone = QtCore.pyqtSignal(int)

    def __init__(self,origen,destino,tamaño_origen):
        QtCore.QThread.__init__(self)
        self.origen = origen
        self.destino = destino
        self.tamaño = tamaño_origen

    def run(self):
        self.copy()
        self.procDone.emit(True)

    def copy(self):
        print("copi hilo")
        source_destino = 'C:/Program Files/SchoolAdministration'
        self.total_destino = 0

        while self.tamaño > self.total_destino:
            for source,dirs,files in os.walk(source_destino):
                for f in files:
                    fp = os.path.join(source,f)
                    self.total_destino+= os.path.getsize(fp)
                    print(self.total_destino,self.tamaño)
                    self.procPartDone.emit(self.total_destino*100/self.tamaño)



class MessageError(threading.Thread):
    def __init__(self,obj):
        threading.Thread.__init__(self)
        self.obj = obj

    def run(self):
        QtCore.QMetaObject.invokeMethod(self.obj,"onError",
            QtCore.Qt.QueuedConnection,
            QtCore.Q_ARG(str,"Critical Access"),
            QtCore.Q_ARG(str,"\nEste programa solo puede ejecutarse con permisos de Administrador.\n\nInfo:\nAsegurese de iniciar el programa con permisos de Administrador\n"))

class Install(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        uic.loadUi("Dialog_Install.ui",self)

        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)

        self.BClose.clicked.connect(self.Info)
        self.BIniciar.pressed.connect(self.Button_Effect_start)
        self.BIniciar.released.connect(self.Button_Effect_End)
        self.progressBar.hide()


    def Info(self):
        respuesta  = QMessageBox.question(None,"Salir","Desea finalizar la intalación del programa\t")
        if respuesta == QMessageBox.Yes:
            self.close()

    def Button_Effect_start(self):
        animacion = QtCore.QPropertyAnimation(self.BIniciar, b"size")
        animacion.setDuration(100)
        animacion.setStartValue(QtCore.QSize(138,28))
        animacion.setEndValue(QtCore.QSize(138,28))
        animacion.start()

    def Button_Effect_End(self):
        animacion = QtCore.QPropertyAnimation(self.BIniciar, b"size")
        animacion.setDuration(100)
        animacion.setStartValue(QtCore.QSize(141,31))
        animacion.setEndValue(QtCore.QSize(141,31))
        animacion.start()
        self.BIniciar.hide()
        self.progressBar.show()
        self.LEstado.setText("Copiando archivos " + str(self.progressBar.value()) + "%")
        self.label_5.setText("Instalando")
        self.LEstado.setText("Creando directorio")
        t=threading.Thread(target=self.Ubicacion)
        t.start()

    def Ubicacion(self):

        arquitectura = platform.architecture()

        target = "Src_School_Admin"
        initial_dir = 'C:\\'
        path = ''

        for root, _,files in os.walk(initial_dir):
            if target in root:
                path = os.path.join(root)
                break


        tamaño_origen = 0
        start = "."
        source = path.replace("\\","/")

        for source,dirs,files in os.walk(source):
            for f in files:
                fp = os.path.join(source,f)
                tamaño_origen += os.path.getsize(fp)

        if os.path.exists('C:\\Program Files\\SchoolAdministration'):
            shutil.rmtree('C:\\Program Files\\SchoolAdministration')
            self.copy1(path,tamaño_origen)

        else:

            self.copy1(path,tamaño_origen)



    def copy1(self,path,tamaño_origen):
        origen = path.replace("\\",'/')
        print(origen)
        destino = 'C:\\Program Files\\SchoolAdministration'
        shutil.copytree(origen, destino)
        self.copy_thread = CopyThread(origen, destino,tamaño_origen)
        self.copy_thread.procPartDone.connect(self.update_progress)
        self.copy_thread.procDone.connect(self.finished_copy)
        self.copy_thread.start()

    def update_progress(self,progress):
        print(progress,"progress")
        self.progressBar.setValue(progress)
    def finished_copy(self,state):
        self.close()


    @QtCore.pyqtSlot(str,str)
    def onError(self,title,text):
        QMessageBox.critical(None,title,text)
        self.close()

app = QApplication([])
i = Install()
i.show()
app.exec_()

Dialog_Install.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>638</width>
    <height>433</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <property name="styleSheet">
   <string notr="true">background:#2A2E30;</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="BClose">
    <property name="geometry">
     <rect>
      <x>600</x>
      <y>0</y>
      <width>41</width>
      <height>31</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Arial</family>
      <pointsize>11</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">QPushButton#BClose{
background:none;
border:0px;
color:white;
}
</string>
    </property>
    <property name="text">
     <string>X</string>
    </property>
   </widget>
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>30</x>
      <y>30</y>
      <width>81</width>
      <height>81</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">background:none;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="pixmap">
     <pixmap>Src_School_Admin/Img/Logo.png</pixmap>
    </property>
    <property name="scaledContents">
     <bool>true</bool>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>40</y>
      <width>121</width>
      <height>21</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>11</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">color:#4253F4;
background:none;</string>
    </property>
    <property name="text">
     <string>School Admin</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_3">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>60</y>
      <width>201</width>
      <height>21</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>10</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">color:#424D99;
background:none;</string>
    </property>
    <property name="text">
     <string>School Administration System</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_4">
    <property name="geometry">
     <rect>
      <x>5</x>
      <y>410</y>
      <width>201</width>
      <height>21</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>8</pointsize>
      <weight>50</weight>
      <bold>false</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">color:grey;
background:none;</string>
    </property>
    <property name="text">
     <string>2019 v 0.1 Beta - Rev.1.0</string>
    </property>
   </widget>
   <widget class="QPushButton" name="BIniciar">
    <property name="geometry">
     <rect>
      <x>250</x>
      <y>270</y>
      <width>141</width>
      <height>31</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>9</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">QPushButton#BIniciar{
color:white;
background:qlineargradient(spread:pad, x1:0.475435, y1:0, x2:0.495, y2:1, stop:0 rgba(66, 83, 224, 255), stop:1 rgba(66, 77, 153, 255));
border:0px;
}
QPushButton#BIniciar:hover{
background:qlineargradient(spread:pad, x1:0.509, y1:1, x2:0.506299, y2:0, stop:0 rgba(66, 83, 224, 255), stop:1 rgba(66, 77, 153, 255));
}</string>
    </property>
    <property name="text">
     <string>Instalar</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_5">
    <property name="geometry">
     <rect>
      <x>250</x>
      <y>190</y>
      <width>141</width>
      <height>20</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>11</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">color:lightgrey;</string>
    </property>
    <property name="text">
     <string>Bienvenido</string>
    </property>
    <property name="alignment">
     <set>Qt::AlignCenter</set>
    </property>
   </widget>
   <widget class="QProgressBar" name="progressBar">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>280</y>
      <width>601</width>
      <height>23</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">QProgressBar#progressBar::horizontal{
border:0px;
background:grey;
}
QProgressBar#progressBar::chunk{
border:0px;
background-color:qlineargradient(spread:pad, x1:1, y1:0.54, x2:0, y2:0.5, stop:0 rgba(45, 116, 185, 193), stop:1 rgba(26, 44, 53, 255));
}</string>
    </property>
    <property name="value">
     <number>0</number>
    </property>
    <property name="textVisible">
     <bool>false</bool>
    </property>
    <property name="invertedAppearance">
     <bool>false</bool>
    </property>
   </widget>
   <widget class="QLabel" name="LEstado">
    <property name="geometry">
     <rect>
      <x>240</x>
      <y>320</y>
      <width>171</width>
      <height>21</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>9</pointsize>
      <weight>50</weight>
      <bold>false</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">color:#4253F4;
background:none;</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="alignment">
     <set>Qt::AlignCenter</set>
    </property>
   </widget>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

Upvotes: 1

Views: 258

Answers (1)

S. Nick
S. Nick

Reputation: 13691

I tried your example, everything is fine, QProgressBar is updated, only very quickly :) so I slowed it down a bit, QtCore.QThread.msleep (100).

# ...
def copy(self):
    print("copi hilo-> {}({}) -> {}".format(self.origen, self.tamaño, self.destino))
    source_destino = 'C:/Program Files/SchoolAdministration'
    #source_destino = 'D:\\Test\\SchoolAdministration'
    self.total_destino = 0

    while self.tamaño > self.total_destino:
        for source, dirs, files in os.walk(source_destino):
            for f in files:
                fp = os.path.join(source, f)
                self.total_destino += os.path.getsize(fp)
                print("\nemit-> {} = {} * 100 / {} "
                      "".format(self.total_destino*100//self.tamaño,     # //
                                self.total_destino, 
                                self.tamaño))
                print("f=`{}` --> fp=`{}`"
                      "".format( f, fp))

                self.procPartDone.emit(self.total_destino*100/self.tamaño)

                QtCore.QThread.msleep(100)                               # <---
# ...

enter image description here

Upvotes: 3

Related Questions