Qt 在主线程外创建QDialog的方法

Qt 在主线程外创建QDialog的方法,qt,qthread,Qt,Qthread,我正在尝试在QT中创建一个客户端应用程序,它需要处理线程和可变数量的窗口实例。但是我很难弄清楚如何在一个处理线程内创建一个新窗口。我知道所有ui元素必须与QApplication类在同一个线程中创建,但我需要能够实例化,或者至少在另一个线程中引用QDialog 线程和QDialog之间的通信可以使用信号完成,我并不担心这一点,但实际上创建窗口是另一回事。我可以使用信号告诉主线程创建一个窗口实例,然后以某种方式检索指向它的指针,但对我来说,这似乎有点复杂和难看。有没有更好的方法来完成这样的任务?要

我正在尝试在QT中创建一个客户端应用程序,它需要处理线程和可变数量的窗口实例。但是我很难弄清楚如何在一个处理线程内创建一个新窗口。我知道所有ui元素必须与QApplication类在同一个线程中创建,但我需要能够实例化,或者至少在另一个线程中引用QDialog
线程和QDialog之间的通信可以使用信号完成,我并不担心这一点,但实际上创建窗口是另一回事。我可以使用信号告诉主线程创建一个窗口实例,然后以某种方式检索指向它的指针,但对我来说,这似乎有点复杂和难看。有没有更好的方法来完成这样的任务?要在主线程外创建QDialog,QApplication类是否存在

编辑:我尝试了Q_可调用方法,但它不能跨线程工作。我创建了一个视图工厂类,它可以创建我指定类型的QDialog并返回指向它的指针。该类已在主GUI线程中实例化,对该类的引用将发送到任何工作线程。问题是,当线程使用Qt::BlockingQueuedConnection从工厂调用create方法时,调用方法失败。如果我将其更改为Qt::DirectConnection,invoke方法将调用正确的create方法,但在当前线程中作为工作线程

我的主要功能如下所示:

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();
    .............................

}
void ClientApp::run()
{
    QDialog * tmp = NULL;
    QMetaObject::invokeMethod(this->_vFactory, "create", Qt::BlockingQueuedConnection,
                        Q_RETURN_ARG(QDialog*, tmp), Q_ARG(int, 0));
}
ClientApp线程中的run函数如下所示:

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();
    .............................

}
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不会失败,因此参数不是问题所在,而是跨单独的工作线程调用该方法。

您只能在Gui线程中执行Gui操作。显而易见的解决方案是工作线程向gui线程发送一条消息=用Qt表示的信号

如果工作线程需要询问问题,它应该向gui线程发送一条消息,然后阻塞,直到收到信号为止。

AFAIK、信号(或者只是一个动态可调用的方法,使用)或事件是解决方法


请注意,使用(with),您可以跨线程安全地调用函数,并在不进行太多编码的情况下返回返回值。

似乎
QObject::moveToThread
可以解决此问题。此函数用于将事件处理循环移动到另一个线程

Qt文档中的示例:


使用Q_INVOKABLE解决了这个问题。失败的原因是,当使用Qt::BlockingQueuedConnection作为连接类型时,不能将Q_RETURN_ARG作为参数传递,只能传递简单的参数。对于排队连接,ARG类型由Qt转换并存储在事件中。为了让Qt在这方面取得成功,由于模板的魔力,您需要正确地向Qt注册您的类型。这是一个很好的答案,即使在10年后,它仍然非常有用。