在主线程外创建 QDialog 的方法
我正在尝试在 QT 中创建一个客户端应用程序,它需要处理线程和可变数量的窗口实例.但是我很难弄清楚如何在其中一个处理线程中创建一个新窗口.我知道所有 ui 元素都必须在与 QApplication 类相同的线程中创建,但我需要能够实例化,或者至少在另一个线程中有对 QDialog 的引用.
线程和 QDialog 之间的通信可以使用信号来完成,我不担心这一点,但实际上创建窗口是另一回事.我可以使用信号告诉主线程为窗口创建一个实例,然后以某种方式检索指向它的指针,但对我来说这似乎有点复杂和丑陋.有没有更好的方法来完成这样的任务?在主线程之外创建 QDialog 是否存在 QApplication 类?
编辑:我尝试了 Q_INVOKABLE 方法,但它不能跨线程工作.我创建了一个视图工厂类,它可以创建一个我指定的类型的 QDialog 并返回一个指向它的指针.此类已在主 GUI 线程中实例化,并且将对此类的引用发送到任何工作线程.问题是,当线程使用 Qt::BlockingQueuedConnection 从工厂调用 create 方法时,调用方法失败.如果我将其更改为 Qt::DirectConnection,则 invoke 方法调用正确的 create 方法,但在当前线程中作为工作线程.
我的主要功能如下所示:
I am trying to create a client application in QT which requires both threads for processing and a variable amount of window instances. But I am having a hard time trying to figure out how to create a new window inside one of the processing thread. I understand that all ui elements must be created in the same thread as the QApplication class, but I need to be able to instantiate, or at least have a reference to a QDialog in another thread.
Communicating between the thread and QDialog can be done using signals, I am not worried about this, but actually creating the window is another matter. I could use signals to tell the main thread to create an instance to the window, and then retrieve the pointer to it somehow, but to me that seems a bit to complicated and ugly. Is there a better way to accomplish such a task? To create a QDialog outside the main thread were the QApplication class exists?
Edit : I have tried the Q_INVOKABLE method but it does not work across threads. I have created a view factory class which can create a QDialog of a type I specify and returns a pointer to it. This class has been instantiated in the main GUI thread and a reference to this class is sent to any worker threads. The problem is that, when a thread invokes the create method from the factory using Qt::BlockingQueuedConnection, the invoke method fails. If I change it to Qt::DirectConnection, the invoke method calls the right create method but in the current thread as the worker thread.
My main function looks like this :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ViewFactory vFactory;
vFactory.registerCreator(Util::W_CONNECT, new ConnectWindow::ConnectCreator());
ClientApp app;
if(!app.Initialize(&vFactory))
return 0;
app.start();
a.exec();
.............................
}
我的 ClientApp 线程中的运行函数如下所示:
And my run function from the ClientApp thread looks something like this :
void ClientApp::run()
{
QDialog * tmp = NULL;
QMetaObject::invokeMethod(this->_vFactory, "create", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QDialog*, tmp), Q_ARG(int, 0));
}
就像我说的,如果我将连接类型更改为 Qt::DirectConnection,invokeMothod 不会失败,因此参数不是问题,而是跨单独的工作线程调用该方法.
Like I said, the invokeMothod will not fail if I change the connection type to Qt::DirectConnection, so the params are not the problem, but rather calling the method across a separate worker thread.
AFAIK、信号(或只是一个动态可调用方法,使用 Q_INVOKABLE
) 或事件是要走的路.
AFAIK, signals (or just a dynamically callable method, using Q_INVOKABLE
) or an event is the way to go.
请注意,使用 QMetaObject::invokeMethod()代码>
(使用Qt::BlockedConnection
),您可以安全地跨线程调用函数并获得返回值,而无需过多编码.
Note that, using QMetaObject::invokeMethod()
(with Qt::BlockedConnection
), you can call a function safely across threads and get a return value back without too much coding.