У меня есть следующая проблема: наше основное приложение использует набор инструментов Qt для отображения окон и взаимодействия с пользователем. Однако большая часть нашего приложения не знает часть GUI. Теперь я создал следующий дизайн:Обработка сигнала усиления в приложении Qt с несколькими потоками
- Там одноэлементно класс, который может запросить рендеринг для данного объекта (OpenSceneGraph узел, но это не имеет никакого отношения к этому вопросу)
- запрос рендеринга вызывает одноплодное испускать сигнал
- Существует слот в главном классе окна (который использует Qt) для обработки визуализации объекта
- в настоящее время, слот только создает новый текст редактирование виджета и помещает его в
QMdiArea
главного окна
Тем не менее, приложение неизбежно сбой, когда я пытаюсь создать новый виджет. Сообщения об ошибках площадь:
QObject::setParent: Cannot set parent, new parent is in a different thread
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
myApplication: ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Aborted
Ознакомившись StackOverflow, я нашел подобные вопросы (которые не были легко применимы к данной ситуации). Очевидно, Qt не нравится, когда я что-то меняю в главном окне из другого потока. Тем не менее, я не сознательно создать новую тему, и я подумал, что синглтон (который создается в главной функции сразу после вызова QApplication()
) должен быть в же потоке как Qt. Видимо, я ошибаюсь.
Вот минимальный пример, который показывает то, что я делаю (я извлек соответствующие части кода, так что пример не совсем функциональный):
class Object
{
public:
};
class Singleton
{
public:
typedef boost::signals2::signal<void (Object*)> signalShowObject;
signalShowObject _showObject;
};
class MainWindow : public QMainWindow
{
public:
MainWindow()
{
Singleton::getInstance()->_showObject.connect(boost::bind(&MainWindow::showObject, this, _1));
// Set up MDI area etc.
}
private:
QMdiArea* _mdiArea;
void showObject(Object* object)
{
// Creating a new subwindow here causes the crash. The `object` pointer is
// not used and has just been included because it models my real problem
// better.
_mdiArea->addSubWindow(new QTextEdit())->show();
}
};
Мои попытки решить эту проблему есть был очень неуклюжим:
- Я создал новый Qt сигнал в
MainWindow
классе с той же подписью, что и сигнала бустера - в сл ВЗ, который обрабатывает сигнал Boost, я испускаю новый
Qt
сигнал, передавая указатель на - теперь я создал новый Qt слота, который получает указатель
Когда я открываю новое окно в новом слоте , все работает. Однако это кажется мне очень неуклюжим. Нужно ли мне cascadeвсе Усиление сигналов так или есть лучший способ?
Просто, чтобы быть ясным. Каждая операция gui ДОЛЖНА выполняться в потоке QApplication. Если вы хотите проверить, вызван ли ваш метод в правильном потоке, используйте qDebug() << thread() << QThread :: currentThread(); Сообщите нам, что является результатом этой отладки в элементе showObject. –
@KamilKlimek Я получил идентификаторы потоков в моем «реальном» приложении, и они действительно разные. – Gnosophilon
Вы можете вызвать слоты, а затем с QMetaObject :: invokeMethod –