I am trying to get a QProgressBar to show the progress of a file copy in PyQt. I've looked about and I've got as far as running the actual copy in a thread using QFile. I just can't get the bar to update though.
Here's some code:
class ProgressDialog(QtGui.QDialog):
def __init__(self, parent, source, destination):
QtGui.QDialog.__init__(self, parent)
self.parent = parent
self.source = source
self.destination = destination
self.add_diag = progress_diag.Ui_Dialog()
self.add_diag.setupUi(self)
self.add_diag.infoLabel.setText("Copying: %s" % (self.source))
self.sourcefile = QtCore.QFile(self.source)
self.add_diag.progressBar.setMinimum(0)
self.add_diag.progressBar.setMaximum(self.sourcefile.size()/1024)
self.written = 0
self.show()
self.copy()
def copy(self):
copy_thread = CopyThread(self, self.sourcefile, self.destination)
self.connect(copy_thread.destination_file, QtCore.SIGNAL("bytesWritten(qint64)"), self.update_progress)
copy_thread.procDone.connect(self.finished_copy)
copy_thread.start()
def update_progress(self, progress):
print "Working", progress
sel开发者_Python百科f.written += progress
self.add_diag.progressBar.setValue(written/1024)
def finished_copy(self, state):
self.close()
class CopyThread(QtCore.QThread):
procDone = QtCore.pyqtSignal(bool)
def __init__(self, parent, source, destination):
QtCore.QThread.__init__(self, parent)
self.source = source
self.destination_file = QtCore.QFile(destination)
def run(self):
self.source.copy(self.destination_file.fileName())
self.procDone.emit(True)
update_progess never gets called so the signal obviously isn't being emitted but I'm not sure why.
I've searched high and low on this but haven't found a good PyQt solution for this so any help would be great.
Ok so here's what I came up with which works but obviously slows down the file copy performance.
class ProgressDialog(QtGui.QDialog):
def __init__(self, parent, source, destination):
QtGui.QDialog.__init__(self, parent)
self.parent = parent
self.source = source
self.destination = destination
self.add_diag = progress_diag.Ui_Dialog()
self.add_diag.setupUi(self)
self.add_diag.infoLabel.setText("Copying: %s" % (self.source))
self.add_diag.progressBar.setMinimum(0)
self.add_diag.progressBar.setMaximum(100)
self.add_diag.progressBar.setValue(0)
self.show()
self.copy()
def copy(self):
copy_thread = CopyThread(self, self.source, self.destination)
copy_thread.procPartDone.connect(self.update_progress)
copy_thread.procDone.connect(self.finished_copy)
copy_thread.start()
def update_progress(self, progress):
self.add_diag.progressBar.setValue(progress)
def finished_copy(self, state):
self.close()
class CopyThread(QtCore.QThread):
procDone = QtCore.pyqtSignal(bool)
procPartDone = QtCore.pyqtSignal(int)
def __init__(self, parent, source, destination):
QtCore.QThread.__init__(self, parent)
self.source = source
self.destination = destination
def run(self):
self.copy()
self.procDone.emit(True)
def copy(self):
source_size = os.stat(self.source).st_size
copied = 0
source = open(self.source, "rb")
target = open(self.destination, "wb")
while True:
chunk = source.read(1024)
if not chunk:
break
target.write(chunk)
copied += len(chunk)
self.procPartDone.emit(copied * 100 / source_size)
source.close()
target.close()
QFile does not emit bytesWritten:
Unlike other QIODevice implementations, such as QTcpSocket, QFile does not emit the aboutToClose(), bytesWritten(), or readyRead() signals. This implementation detail means that QFile is not suitable for reading and writing certain types of files, such as device files on Unix platforms.
http://doc.qt.nokia.com/latest/qfile.html
You will have to implement your own loop and emit the progress yourself.
精彩评论