在GUI线程之外调用QAxWidget方法

时间:2010-05-14 14:14:33

标签: multithreading qt activex

我开始怀疑这是否是不可能的,但我想我会问,以防巧妙地解决我遇到的问题。

我有一个使用ActiveX控件的Qt应用程序。控件由QAxWidget保存,QAxWidget本身包含在另一个QWidget中(我需要向窗口小部件添加额外的信号/插槽,我不能只是将QAxWidget子类化,因为类不允许这样做)。当我需要与ActiveX控件交互时,我调用QWidget的方法,QWidget又调用QAxWidget的dynamicCall方法,以便调用ActiveX控件的相应方法。所有这些都很好。

但是,ActiveX控件的一种方法需要几秒钟才能返回。当我调用此方法时,我的整个GUI会锁定几秒钟,直到方法返回。这是不可取的。我希望ActiveX控件可以自行完成处理,并在完成操作时返回给我,而不会锁定Qt GUI。

我尝试了一些没有成功的事情:

  • 从新线程创建一个新的QThread并调用QAxWidget :: dynamicCall
  • 将信号连接到QAxWidget的相应插槽方法,并使用信号/插槽调用方法,而不是使用dynamicCall
  • 使用QtConcurrent :: run调用QAxWidget :: dynamicCall

似乎没有什么影响这种行为。无论我使用dynamicCall的方式或位置(或触发QAxWidget的相应插槽),GUI都会锁定,直到ActiveX控件完成其操作。

有没有办法从Qt GUI线程中分离这个ActiveX处理,以便在ActiveX控件运行方法时GUI不会锁定?有什么聪明的我可以用QAxBase或QAxObject来获得我想要的结果吗?

2 个答案:

答案 0 :(得分:3)

经过一些实验,我能够通过做一些我认为我之前尝试过的事情来解决这个问题:创建一个新的QThread并从新线程调用QAxWidget :: dynamicCall。我第一次尝试这个解决方案时,一定不能正确编码;与同事坐在一起后,我们能够让它发挥作用。具体而言,我们所做的是:

(步骤1)创建了QThread的子类来表示我需要调用dynamicCall()的线程。

(步骤2)在我的QThread的构造函数中,传入指向我原始QAxWidget的指针,并将指针保存在成员变量中。

MyThread::MyThread(QAxWidget* passedWidget) : QThread()  
{  
    actualWidget = passedWidget;  
}  

(步骤3)在QThread的run()方法中,调用QAxWidget的dynamicCall()方法。

void MyThread::run()  
{  
    QVariant result = actualWidget->dynamicCall(...parms as necessary...);  
}  

(步骤4)回到我的主代码中,当我需要执行dynamicCall()时,我只需要调用MyThread的start()方法。 start()方法将在其自己的线程中执行run(),从而向ActiveX对象发送必要的命令,而不会阻塞或停止主GUI线程。

答案 1 :(得分:0)

如果不需要事件循环,则不需要子类化QThread!我认为这是解决这个问题的方法,没有一大堆信号到主线程(很可能)拥有QAxWidget。 Qt 5.3中关于QThread的最新文档也证实了这一点。