在进行计算时保持GIF动画运行

时间:2016-08-09 21:24:41

标签: multithreading python-2.7 pyqt4

我正在尝试通过在执行需要一些时间的任务时在活动QMainWindow / QDialog上方显示加载掩码来改善用户体验。我已经设法让它按照我想要的方式工作,除了在执行任务时移动的GIF。如果在任务完成后我打开负载模板,GIF将按原样开始移动。

我的加载掩码类:

from PyQt4 import QtGui, QtCore
from dlgLoading_view import Ui_dlgLoading

class dlgLoading(QtGui.QDialog, Ui_dlgLoading):
    def __init__(self,parent):
        QtGui.QDialog.__init__(self,parent)

        self.setupUi(self)
        self.setWindowFlags(QtCore.Qt.WindowFlags(QtCore.Qt.FramelessWindowHint))
        self.setGeometry(0, 0, parent.frameGeometry().width(), parent.frameGeometry().height())
        self.setStyleSheet("background-color: rgba(255, 255, 255, 100);")

        movie = QtGui.QMovie("loader.gif")
        self.lblLoader.setMovie(movie)
        movie.start()

    def showEvent(self, event):
        QtGui.qApp.processEvents()
        super(dlgLoading, self).showEvent(event)

    def setMessage(self,message):
        self.lblMessage.setText(message)

Ui_dlgLoading包含两个标签和一些垂直间隔:lblLoader(将包含gif)和lblMessage(如果需要,将包含一条消息)

我使用以下代码创建加载掩码:

loadmask = dlgLoading(self)
loadmask.setMessage('Reading data... Please wait')
loadmask.show()

我认为我需要一些多线程/多处理,但我不能为我的生活找出如何做到这一点。我在某处读到了你可以篡改图形用户界面的线程,所以我需要把繁重的任务转移到那里,但我还是空白。

作为一个简单的例子,让我们说我正在尝试将一个巨大的文件加载到内存中:

file = open(dataFilename, 'r')
self.dataRaw = file.read()
file.close()

我将创建并关闭我的加载掩码对话框。如何在不停止GIF动画的情况下启动文件读取?

GUI用于运行一些繁重的外部exe文件,因此它也可以使用它。

1 个答案:

答案 0 :(得分:0)

我最终这样做了:

class runthread(threading.Thread):
    def __init__(self, commandline, cwd):
        self.stdout = None
        self.stderr = None
        self.commandline = commandline
        self.cwd = cwd
        self.finished = False
        threading.Thread.__init__(self)

    def run(self):
        subprocess.call(self.commandline, cwd=self.cwd)
        self.finished = True

class command()
    def __init__(self):
        ...

    def run():
        ...

        thread = runthread("\"%s\" \"%s\"" % (os.path.join(self.__caller.exefolder, "%s.exe" % self.__cmdtype), self.__name), self.__caller.exeWorkdir)
        thread.start()

        count = 0
        sleeptime = 0.5
        maxcount = 60.0/sleeptime
        while True:
            time.sleep(sleeptime)
            QtWidgets.qApp.processEvents()
            count += 1
            if thread.finished:
                break
            if count >= maxcount:
                results = QtWidgets.QMessageBox.question(self.__caller, "Continue?", "The process is taking longer than expected. Do you want to continue?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
                if results == QtWidgets.QMessageBox.Yes:
                    count == 0
                else:
                    QtWidgets.QMessageBox.warning(self.__caller, "Process stopped", "The process was stopped")
                    return False

它实际上并没有直接回答我的问题,但它对我有用,所以如果其他人想要做类似的话,我会发布答案。

我通过一个线程调用一个进程(在本例中为Pythons subprocess.call)并跟踪进程实际完成的时间。连续循环定期检查过程是否完成并更新GUI(processEvents - 这是触发GIF更新的原因)。为避免无限循环,我会在一段时间后为用户提供退出选项。