PyQt: QtGui.QFileDialog.getSaveFileName 选择后不关闭

3 投票
1 回答
3729 浏览
提问于 2025-04-17 17:12

在我的PyQt4应用程序中,有一个功能可以让用户保存一个avi文件。为此,我在主窗口里实现了一个saveMovie的方法:

def saveMovie(self):
    """ Let the user make a movie out of the current experiment. """
    filename = QtGui.QFileDialog.getSaveFileName(self, "Export Movie", "",
                                                 'AVI Movie File (*.avi)')

    if filename != "":
        dialog = QtGui.QProgressDialog('',
                                       QtCore.QString(),
                                       0, 100,
                                       self,
                                       QtCore.Qt.Dialog |
                                       QtCore.Qt.WindowTitleHint)

        dialog.setWindowModality(QtCore.Qt.WindowModal)
        dialog.setWindowTitle('Exporting Movie')
        dialog.setLabelText('Resampling...')

        dialog.show()

        make_movie(self.appStatus, filename, dialog)

        dialog.close()

我的想法是使用一个QProgressDialog来显示视频编码的进度。
不过,在选择文件名之后,QFileDialog不会消失,整个应用程序在make_movie函数完成之前都没有反应。

我该怎么做才能避免这种情况呢?

1 个回答

2

经验教训:如果你有一些需要长时间运行的操作,比如读取或写入一个很大的文件,最好把它们放到另一个线程去执行,不然会导致界面卡住。

因此,我创建了一个叫做 MovieMakerQThread 子类,它的 run 方法包含了之前在 make_movie 中实现的功能:

class MovieMaker(QThread):
    def __init__(self, uAppStatus, uFilename):
        QtCore.QThread.__init__(self, parent=None)
        self.appStatus = uAppStatus
        self.filename = uFilename

    def run(self):
        ## make the movie and save it on file

接下来,我们回到 saveMovie 方法。在这里,我把原来调用 make_movie 的代码替换成了以下代码:

self.mm = MovieMaker(self.appStatus,
                     filename)

self.connect(self.mm, QtCore.SIGNAL("Progress(int)"),
             self.updateProgressDialog)

self.mm.start()

注意我定义了一个新的信号,叫做 Progress(int)
这个信号是由 MovieMaker 线程发出的,用来更新 QProgressDialog,让用户知道电影编码的进度如何。

撰写回答