我有一个Qt应用程序,需要调用一个昂贵的非Qt函数(例如,解压缩一个~200 up的压缩文件),而且由于我从主/ GUI线程调用该函数,所以Qt一直冻结到操作完成(有时是5-10秒)。
我知道避免这个问题的一种方法是从一个单独的线程调用昂贵的函数,但是由于在解压缩完成之前,用户无法做太多的事情,这似乎有点过分了。我不能将processEvents()调用添加到昂贵的函数本身中,因为该函数是非Qt识别的代码基的一部分,我不想向它添加Qt依赖项。
那么,我唯一想要更改的是,在GUI被阻塞的时候,会出现一条“请等待”类型的消息,这样用户就不会认为他的鼠标点击被忽略了。
我现在这样做:
BusySplashWidget * splash = new BusySplashWidget("Please wait…", this);
splash->show();
qApp->processEvents(); // make sure that the splash is actually visible at this point?
ReadGiantZipFile(); // this can take a long time to return
delete splash;这在95%的时间内都能工作,但偶尔不会出现splash小部件,或者它只是一个灰色矩形,“请等待”文本是不可见的。
我的问题是,除了qApp->processEvents()之外,还有其他调用可以保证在漫长的操作开始之前,splash小部件完全可见吗?(我想我可以一次又一次地调用qApp->processEvents()一次又一次地调用100 if,或者什么的,以使Qt相信我是认真的,但如果可能的话,我希望避免基于巫毒的编程;)
如果这很重要,下面是我如何实现我的BusySplashWidget构造函数:
BusySplashWidget :: BusySplashWidget(const QString & t, QWidget * parent) : QSplashScreen(parent)
{
const int margin = 5;
QFontMetrics fm = fontMetrics();
QRect r(0,0,margin+fm.width(t)+margin, margin+fm.ascent()+fm.descent()+1+margin);
QPixmap pm(r.width(), r.height());
pm.fill(white);
// these braces ensure that ~QPainter() executes before setPixmap()
{
QPainter p(&pm);
p.setPen(black);
p.drawText(r, Qt::AlignCenter, t);
p.drawRect(QRect(0,0,r.width()-1,r.height()-1));
}
setPixmap(pm);
}发布于 2014-03-26 19:37:44
移动到另一个线程是正确的方法,但是对于简单的操作,有一种不需要管理线程的复杂得多的方法来完成这一任务。
BusySplashWidget splash("Please wait…", this);
QFutureWatcher<void> watcher;
connect(&watcher, SIGNAL(finished()), &splash, SLOT(quit()));
QFuture<void> future = QtConcurrent::run(ReadGiantZipFile);
watcher.setFuture(future);
splash.exec(); // use exec() instead of show() to open the dialog modally有关 framework的更多信息,请参阅有关该文档。
https://stackoverflow.com/questions/22670564
复制相似问题