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

发布于 2024-10-19 21:37:56 字数 1311 浏览 3 评论 0原文

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

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

我的主要函数如下所示:

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 线程的运行函数如下所示:

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 不会失败,所以参数不是问题,但是而是通过单独的工作线程调用该方法。

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

}

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));
}

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

遥远的她 2024-10-26 21:37:56

你只能在 gui 线程中做 Gui 的事情。显而易见的解决方案是工作线程向 gui 线程发送消息 = Qt 术语中的信号。

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

You can only do Gui stuff in the gui thread. The obvious solution is for the worker thread to send a message to the gui thread = a signal in Qt terms.

If a worker thread needs to ask a question it should send a message to the gui thread and then block until it gets a signal back.

木落 2024-10-26 21:37:56

AFAIK,信号(或者只是一个动态可调用方法,使用 Q_INVOKABLE)或事件是可行的方法。

请注意,使用 QMetaObject::invokeMethod()< /a> (带有 Qt::BlockedConnection ),您可以跨线程安全地调用函数并获取返回值,而无需太多编码。

AFAIK, signals (or just a dynamically callable method, using Q_INVOKABLE) or an event is the way to go.

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.

绝情姑娘 2024-10-26 21:37:56

看起来QObject::moveToThread可以解决这个问题。该函数将事件处理循环移动到另一个线程。

Qt 文档中的示例:

myObject->moveToThread(QApplication::instance()->thread());

It seems like QObject::moveToThread can solve this problem. This function moves event processing loop to another thread.

Example from Qt documentation:

myObject->moveToThread(QApplication::instance()->thread());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文