简体   繁体   中英

qt signals/slots in a plugin

I have an app with such structure: all the datatypes ( class INode ) are stored in plugins (DLLs). Some of the datatypes can be drawn (if they're IDrawable ).

To load an object of, eg class PointCloudNode: public INode I have a special input plugin (DLL) which is called class PointCloudParser: public IIOPlugin and IIOPlugin is a thread with some specific functionality: class IIOPlugin: public QThread .

All the objects are created by NodeFactory class which is a singleton stored in separate DLL.

And here's the problem:

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

If I do this from any thread (main thread or the Input Plugin thread)

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

The update launches, the tmptmp() signal is emitted, and the slot ( drawObject() ) executes correctly.

if do just the same, but create the object in my Input Plugin, pass over the shared pointer and execute dr->update() in another function, the slot drawObject() is never entered though all the code is executed (including connect , etc.). 如果执行相同的操作,但是在我的输入插件中创建对象,传递共享指针并在另一个函数中执行dr->update() ,尽管执行了所有代码(包括connect drawObject()却从未输入slot drawObject()等)。

To be more precise, here's the Input Plugin:

 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
 }

The last emit is connected to this:

 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 :(
 }

How come? The node object is the same all the way through, it is valid. Every line in code in launched, QObject::connect doesn't write anything to debug window, the signal tmptmp() is emitted, but the slot drawObject() in one case is never reached? Any ideas?

If I do not inherit IIOPlugin from QThread , everything works fine (ie load the object in the main thread). 如果我没有从QThread继承IIOPlugin ,那么一切都会很好(即,将对象加载到主线程中)。 I expected the signals/slots to work across the threads...

Since you are sending a signal across to a different thread, you might need to explicitly tell Qt that the connection should be a queued one:

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

By default Qt will use Qt::AutoConnection as that last parameter, and it will choose whether to use a direct connection (if the slot is in the same thread as the emitter) or a queued connection (if the slot is in a different thread). But since your thread is in a separate library, maybe Qt isn't making the right assumption here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM