Calling QAxWidget method outside of the GUI thread

☆樱花仙子☆ 提交于 2020-03-05 18:14:23

问题


I'm beginning to wonder if this is impossible, but I thought I'd ask in case there's a clever way to get around the problems I'm having.

I have a Qt application that uses an ActiveX control. The control is held by a QAxWidget, and the QAxWidget itself is contained within another QWidget (I needed to add additional signals/slots to the widget, and I couldn't just subclass QAxWidget because the class doesn't permit that). When I need to interact with the ActiveX control, I call a method of the QWidget, which in turn calls the dynamicCall method of the QAxWidget in order to invoke the appropriate method of the ActiveX control. All of that is working fine.

However, one method of the ActiveX control takes several seconds to return. When I call this method, my entire GUI locks up for a few seconds until the method returns. This is undesirable. I'd like the ActiveX control to go off and do its processing by itself and come back to me when it's done without locking up the Qt GUI.

I've tried a few things without success:

  • Creating a new QThread and calling QAxWidget::dynamicCall from the new thread
  • Connecting a signal to the appropriate slot method of the QAxWidget and calling the method using signals/slots instead of using dynamicCall
  • Calling QAxWidget::dynamicCall using QtConcurrent::run

Nothing seems to affect the behavior. No matter how or where I use dynamicCall (or trigger the appropriate slot of the QAxWidget), the GUI locks until the ActiveX control completes its operation.

Is there any way to detach this ActiveX processing from the Qt GUI thread so that the GUI doesn't lock up while the ActiveX control is running a method? Is there something clever I can do with QAxBase or QAxObject to get my desired results?


回答1:


After some experimentation, I was able to solve this by doing something I thought I'd tried earlier: creating a new QThread and calling QAxWidget::dynamicCall from the new thread. I must not have coded it correctly the first time I tried this solution; after sitting with a co-worker, we were able to get it to work. To be specific, what we did is:

(Step 1) Created a subclass of QThread to represent the thread I need to call dynamicCall().

(Step 2) In the constructor of my QThread, pass in a pointer to my original QAxWidget, and keep the pointer in a member variable.

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

(Step 3) In the run() method of the QThread, call the dynamicCall() method of the QAxWidget.

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

(Step 4) Back in my main code, when I need to execute dynamicCall(), I just call the start() method of MyThread. The start() method will execute run() in its own thread, thus sending the necessary command to the ActiveX object without blocking or stalling the main GUI thread.




回答2:


If there is no event loop needed, then there is no need NOT to subclass QThread! I think this is the way to solve this without a bunch of signals to the main thread which (more than likely) owns the QAxWidget. The latest docs for Qt 5.3 referring to QThread also bears this out.



来源:https://stackoverflow.com/questions/2834781/calling-qaxwidget-method-outside-of-the-gui-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!