开发者

Ways to create a QDialog outside the main thread

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开发者_C百科 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.


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.


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.


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜