前因:有时在窗体初始化的时候加载一个耗时的操作,很容易卡主界面的显示,要在加载完以后才会显示界面,这就导致了体验很卡不友好的感觉,此时你可以将耗时的加载延时或者异步进行加载,这样就会在界面显示后去执行,而不是卡在主界面。
主界面要执行一些耗时的操作时,不卡主界面的方式:
☺方式一(延时)
可以考虑QTimer的单次触发静态函数QTimer::singleShot()
函数原型:void QTimer::singleShot ( int msec, QObject * receiver, const char * member ) [static]
示例1:时间到了之后,只会触发一次
#include <QApplication>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTimer::singleShot(600000, &app, SLOT(quit()));
...
return app.exec();
}
示例2:非阻塞方式延时
QEventLoop loop;
QTimer::singleShot(msec, &loop, SLOT(quit()));
loop.exec();
继续执行代码
//如果不是QTimer的单次触发事件,是其他的执行代码的话,可以用
loop.exit(); //退出事件循环
☺方式二(异步加载耗时函数)
示例:
QMetaObject::invokeMethod(this, "load", Qt::QueuedConnection);
//load要定义成槽函数,耗时操作放在里面执行即可
补充说明:QMetaObject::invokeMethod静态函数可以同来调用一个Q_OBJECT对象的信号、槽、方法,其原型如下所示:(如果可以调用该成员,则返回True。如果没有这样的成员或参数不匹配,则返回FALSE。)
bool QMetaObject::invokeMethod (
QObject * obj,//被调用对象的指针;
const char * member,//参数是方法的名字;
Qt::ConnectionType type,//参数是连接类型。可以指定连接类型,来决定是同步还是异步调用;
QGenericReturnArgument ret,//参数接收被调用函数的返回值;注意,如果调用是异步的,则无法计算返回值;
QGenericArgument val0 = QGenericArgument( 0 ),
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
QGenericArgument val4 = QGenericArgument(),
QGenericArgument val5 = QGenericArgument(),
QGenericArgument val6 = QGenericArgument(),
QGenericArgument val7 = QGenericArgument(),
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument() ) [static]
注1:传入的参数是有个数限制的,可以向成员函数传递最多十个参数(val0,val1,val2,val3,val4,val5,val6,val7,val8和val9)。
注2:第三个参数连接类型区别
Qt :: DirectConnection | 会立即调用该成员 |
Qt :: QueuedConnection | 将发送QEvent,并在应用程序进入主事件循环时立即调用该成员(异步) |
Qt :: BlockingQueuedConnection | 将以与Qt :: QueuedConnection相同的方式调用该方法,除了当前线程将阻塞直到事件被传递。使用此连接类型在同一线程中的对象之间进行通信将导致死锁。 |
Qt :: AutoConnection | 则如果obj与调用者位于同一个线程中,则会同步调用该成员; 否则它将异步调用该成员。 |
注3:QGenericArgument和QGenericReturnArgument是内部帮助器类。因为可以动态调用信号和槽,所以必须使用Q_ARG()和Q_RETURN_ARG()宏将参数括起来。
对于带参数的槽函数调用示例,槽函数是compute(QString, int, double):
QString sReturnVal;
QMetaObject::invokeMethod(object, "compute", Qt::DirectConnection,
Q_RETURN_ARG(QString, sReturnVal),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7));
☺1、Q_RETURN_ARG()接受类型名和非常数引用。
☺2、Q_ARG()接受类型名和该类型的常量引用;
对于异步方法调用,参数必须是Qt的元对象系统已知的类型,因为Qt需要复制参数以将它们存储在幕后的事件中。
注:QMetaObject::InvokeMethod:无法处理未注册的数据类型,在调用InvokeMethod()之前,应该调用qRegisterMetaType()注册数据类型,示例:
typedef QString CustomString;
qRegisterMetaType<CustomString>("CustomString");
大佬经验补充:如果要执行private(protected/public)下的函数,需要函数前面加上 Q_INVOKABLE 关键字,private: Q_INVOKABLE void fun_test(int type, double value);
QMetaObject::invokeMethod(this, "fun_test", Q_ARG(int, 99), Q_ARG(double, 99.99));
或许你会感兴趣!!!