QMetaObject::invokeMethod()使用解决界面卡住问题
前因:有时在窗体初始化的时候加载一个耗时的操作,很容易卡主界面的显示,要在加载完以后才会显示界面,这就导致了体验很卡不友好的感觉,此时你可以将耗时的加载延时或者异步进行加载,这样就会在界面显示后去执行,而不是卡住主界面。
☺延时:可以考虑QTimer的单次触发静态函数QTimer::singleShot()单次触发
☺异步进行load函数:QMetaObject::invokeMethod(this, "load", Qt::QueuedConnection);
☺使用方法,都是把耗时的操作放在对应的槽函数里执行。
补充说明: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]
参数说明:
☺第一个参数是被调用对象的指针;
☺第二个参数是方法的名字;
☺第三个参数是连接类型。可以指定连接类型,来决定是同步还是异步调用。
☺第四个参数接收被调用函数的返回值;注意,如果调用是异步的,则无法计算返回值。
注意:传入的参数是有个数限制的,可以向成员函数传递最多十个参数(val0,val1,val2,val3,val4,val5,val6,val7,val8和val9)。
☺第三个参数类型区别:
Qt :: DirectConnection | 会立即调用该成员 |
Qt :: QueuedConnection | 将发送QEvent,并在应用程序进入主事件循环时立即调用该成员(异步) |
Qt :: BlockingQueuedConnection | 将以与Qt :: QueuedConnection相同的方式调用该方法,除了当前线程将阻塞直到事件被传递。使用此连接类型在同一线程中的对象之间进行通信将导致死锁。 |
Qt :: AutoConnection | 则如果obj与调用者位于同一个线程中,则会同步调用该成员; 否则它将异步调用该成员。 |
QGenericArgument和QGenericReturnArgument是内部帮助器类。因为可以动态调用信号和槽,所以必须使用Q_ARG()和Q_RETURN_ARG()宏将参数括起来。
☺Q_ARG()接受类型名和该类型的常量引用;
☺Q_RETURN_ARG()接受类型名和非常数引用。您只需要将信号或槽的名称传递给此函数,而不是整个签名。例如,若要异步调用QPushButton上的AnimateClick()槽,请使用以下代码:
QMetaObject::InvokeMethod(pushButton,“AnimateClick”,Qt::QueuedConnection);
☺如对于带参数的槽函数调用示例,compute(QString, int, double):
QString retVal;
QMetaObject::invokeMethod(object, "compute", Qt::DirectConnection,
Q_RETURN_ARG(QString, retVal),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7));
对于异步方法调用,参数必须是Qt的元对象系统已知的类型,因为Qt需要复制参数以将它们存储在幕后的事件中。
注:QMetaObject::InvokeMethod:无法处理未注册的数据类型,在调用InvokeMethod()之前,应该调用qRegisterMetaType()注册数据类型,示例:
typedef QString CustomString;
qRegisterMetaType("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));
或许你会感兴趣!!!
QT之connect的第五个参数(信号与槽的使用)
创作打卡挑战赛
赢取流量/现金/CSDN周边激励大奖养殖设备