QT сигналы / слоты в плагине - PullRequest
1 голос
/ 11 июля 2010

У меня есть приложение с такой структурой: все типы данных (class INode) хранятся в плагинах (DLL). Некоторые типы данных могут быть нарисованы (если они IDrawable).

Для загрузки объекта, например, class PointCloudNode: public INode У меня есть специальный плагин ввода (DLL), который называется class PointCloudParser: public IIOPlugin, а IIOPlugin - это поток с некоторыми специфическими функциями: class IIOPlugin: public QThread.

Все объекты создаются классом NodeFactory, который является одноэлементным и хранится в отдельной DLL.

И вот проблема:

void PointCloudNode::update()
{
QObject::connect (this,SIGNAL(tmptmp()),this,SLOT(drawObject()));
emit tmptmp();
}

Если я делаю это из какого-либо потока (основного потока или потока входного плагина)

NodeFactory* fab = NodeFactory::getInstance();
boost::shared_ptr<INode> pc(fab->createNode("pointCloud","myPC"));
boost::shared_ptr<IDrawable> dr = boost::dynamic_pointer_cast<IDrawable>(pc);
dr->update();

Обновление запускается, подается сигнал tmptmp() и слот (drawObject()) выполняется правильно.

НО если сделать то же самое, но создать объект в моем плагине ввода, передать общий указатель и выполнить dr->update() в другой функции, слот drawObject() никогда не вводится, хотя весь код выполняется (включая connect и т. д. .).

Чтобы быть более точным, вот плагин ввода:

 void PointCloudParserPlugin::doLoad(const QString& inputName, boost::shared_ptr<INode> container)
 {
   NodeFactory* factory = NodeFactory::getInstance();
   boost::shared_ptr<INode> node = factory->createNode("pointCloud", inputName);

   // here goes the loading itself, nothing special...

   container->addChild(node); //that's the container where I keep all the objects

   //boost::dynamic_pointer_cast<IDrawable>(container->getChild(inputName))->update();
   //If I uncomment this line, it all works: the slot is launched.  
   emit loadingFinished(inputName); // it executes the following function
 }

Последний излучатель связан с этим:

 void GeomBox::updateVisualization(const QString& fileName)
 {
   boost::shared_ptr<INode> node = container_->getChild(fileName);
   boost::shared_ptr<IDrawable> nodeDrawable = boost::dynamic_pointer_cast<IDrawable>(node);
   nodeDrawable->update(); //this is the problem line: update() executes, connect() works, but the slot never runs :(
 }

Как получилось? Объект node все время одинаков, он действителен. Каждая строка в запущенном коде QObject::connect ничего не записывает в окно отладки, сигнал tmptmp() испускается, но слот drawObject() в одном случае никогда не достигается? Есть идеи?

Upd.: Если я не наследую IIOPlugin от QThread, все работает нормально (т.е. загружает объект в основной поток). Я ожидал, что сигналы / слоты будут работать между потоками ...

1 Ответ

0 голосов
/ 25 августа 2011

Поскольку вы отправляете сигнал в другой поток, вам может потребоваться явно указать Qt, что соединение должно быть в очереди:

QObject::connect(this, SIGNAL(tmptmp()), this, SLOT(drawObject()), Qt::QueuedConnection );

По умолчанию Qt будет использовать Qt::AutoConnection какпоследний параметр, и он будет выбирать, использовать ли прямое соединение (если слот находится в том же потоке, что и эмиттер), или соединение в очереди (если слот находится в другом потоке).Но поскольку ваш поток находится в отдельной библиотеке, возможно, Qt здесь не делает правильного предположения.

...