Способы создания QDialog вне основного потока - PullRequest
4 голосов
/ 26 февраля 2011

Я пытаюсь создать клиентское приложение в QT, которое требует как потоков для обработки, так и переменного количества экземпляров окна.Но я с трудом пытаюсь понять, как создать новое окно внутри одного из потоков обработки.Я понимаю, что все элементы пользовательского интерфейса должны быть созданы в том же потоке, что и класс QApplication, но мне нужно иметь возможность создавать экземпляры или, по крайней мере, иметь ссылку на QDialog в другом потоке.Связь между потоком и QDialog может быть выполнена с помощью сигналов, меня это не беспокоит, но на самом деле создание окна - это другой вопрос.Я мог бы использовать сигналы, чтобы сказать основному потоку создать экземпляр для окна, а затем каким-то образом получить указатель на него, но мне это кажется немного сложным и уродливым.Есть ли лучший способ выполнить такую ​​задачу?Чтобы создать QDialog вне основного потока, существует ли класс QApplication? Редактировать : я пробовал метод Q_INVOKABLE, но он не работает между потоками.Я создал класс фабрики представлений, который может создать QDialog указанного мной типа и возвращает указатель на него.Этот класс был создан в основном потоке графического интерфейса, и ссылка на этот класс отправляется любым рабочим потокам.Проблема заключается в том, что, когда поток вызывает метод create из фабрики, используя Qt :: BlockingQueuedConnection, метод invoke завершается ошибкой.Если я изменяю его на 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();
    .............................

}

А моя функция запуска из потока ClientApp выглядит примерно так:

void ClientApp::run()
{
    QDialog * tmp = NULL;
    QMetaObject::invokeMethod(this->_vFactory, "create", Qt::BlockingQueuedConnection,
                        Q_RETURN_ARG(QDialog*, tmp), Q_ARG(int, 0));
}

Как я уже сказал, invokeMothod не будет работать, если я изменютип соединения с Qt :: DirectConnection, поэтому параметры не являются проблемой, а скорее вызывают метод через отдельный рабочий поток.

Ответы [ 3 ]

3 голосов
/ 26 февраля 2011

AFAIK, сигналы (или просто динамически вызываемый метод с использованием Q_INVOKABLE) или событие - это путь.

Обратите внимание, что, используя QMetaObject::invokeMethod()Qt::BlockedConnection), вы можете безопасно вызывать функцию между потоками и возвращать возвращаемое значение без слишком большого кодирования.

3 голосов
/ 26 февраля 2011

Вы можете делать вещи Gui только в ветке GUI. Очевидное решение для рабочего потока - отправить сообщение в поток GUI = сигнал в терминах Qt.

Если рабочий поток должен задать вопрос, он должен отправить сообщение в поток графического интерфейса и затем блокировать, пока не получит сигнал обратно.

2 голосов
/ 30 июня 2012

Кажется, что QObject::moveToThread может решить эту проблему. Эта функция перемещает цикл обработки событий в другой поток.

Пример из документации Qt:

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