在Qt中,两个插件之间的信号/槽交互

6
基本上,我有一个小程序,它加载两个插件并将它们“连接”起来。第一个插件在加载后创建一个没有标题的标签,并将其添加到主窗口中。第二个插件创建一个动作,该动作将添加到菜单中。因此,我的应用程序只需要加载这些插件并将它们“连接”起来。我所说的“连接”是指标签插件包含一个可以修改标签标题的槽,而动作插件则声明了一个信号。应用程序应该将动作插件信号与标签槽“连接”起来。我不知道如何确切地实现它。我猜想,在动作插件类的实现中,将自定义信号与一个标准信号(触发)“连接”。但无论如何,我的应用程序都没有按照我预期的方式工作。我该如何在我的应用程序中正确连接来自一个插件的信号和另一个插件的槽呢?
以下是我的标签插件代码:
#include "LabelInterface.h"

class LabelPlugin : public LabelInterface {

    Q_OBJECT
    Q_INTERFACES(LabelInterface)

public:
    QLabel* label;
    QLabel* newLabel();
     LabelPlugin() {}
    ~LabelPlugin() {}

public slots:
    void setTextforLabel();
}; 

#include <QtGui>
#include "LabelPlugin.h"

QLabel* LabelPlugin::newLabel() {

    label = new QLabel("");
    return label;
}

void LabelPlugin::setTextforLabel() {

    label->setText("This plugin works fine");
}

// Exporta plugin-ul
Q_EXPORT_PLUGIN2 (labelplugin,LabelPlugin)

动作插件:

    #include "ActionInterface.h"

    class ActionPlugin : public ActionInterface  {

        Q_OBJECT
        Q_INTERFACES (ActionInterface)

    public :
         QAction* myAction;
         QAction* newAction();

        ~ActionPlugin () {}
         ActionPlugin () {}

    public slots:
         void send_signal();

     signals :
         void pushMyAction();
    };

#include <QtGui>
#include "ActionPlugin.h"

QAction* ActionPlugin::newAction() {

    myAction = new QAction("Show text",this);

    return myAction;
}

void ActionPlugin::send_signal() {

    qDebug ()<<"Here";

    QAction::connect (this,SIGNAL(pushMyAction()),this,SIGNAL(triggered()));
}

Q_EXPORT_PLUGIN2 (actionplugin,ActionPlugin)

在我的应用程序中,我尝试加载插件时有以下内容:
   foreach (QString fileName, appDir.entryList(QDir::Files)) {

        qDebug()<<QString(fileName);

        QPluginLoader pluginLoader(appDir.absoluteFilePath(fileName));

        QObject* plugin = pluginLoader.instance();

         if (plugin) {

            ActionInterface* myAction= qobject_cast<ActionInterface*>(plugin);

            if (myAction) {
                action_ = myAction;
                pluginMenu->addAction(action_->newAction());
            }

            LabelInterface* myLabel = qobject_cast<LabelInterface*>(plugin);

            if (myLabel) {
                label_=myLabel;
                layout->addWidget(label_->newLabel());
            }

            if (action_ && label_) {

                qDebug()<<"both loaded";

                action_->send_signal();
                connect(action_, SIGNAL(pushMyAction()),label_, SLOT(setTextforLabel()));
            }
            else qDebug() << "seems one plugin is not loaded";
        }
    }

这可能完全没有任何区别,但也许可以尝试 label_->connect(_action, SIGNAL(pushMyAction())); - John Chadwick
你在控制台输出上没有遇到任何连接错误吗? - Kamil Klimek
自Qt5起,Q_EXPORT_PLUGIN2已被弃用。 - ManuelSchneid3r
1个回答

3

你需要能够从每个插件中访问QObject实例,以便在connect调用中使用它。我建议在接口中添加方法来实现这一点。我见过的一个模式是通过运算符将接口转换为QObject指针,例如:

class MyInterface {
public:
    virtual operator QObject*() = 0;
};

对于是否采用这种方式来说,意见可能有所不同,但它解决了问题(如果你不喜欢该运算符,可以使用名为asQObject()或类似的方法)。


顺便提一下,我也遇到了同样的问题。有时候你想要在插件之间进行 qobject_cast,但总是需要先将它们转换为 QObject,这可能会非常烦人。 - pmr
QPluginLoader::instance 将它们作为 QObjects 返回,我不明白为什么需要将它们强制转换回 QObject? - Kamil Klimek
通常情况下,您会将 qobject_cast 转换为您的接口并使用它,但是没有办法将其转换回 QObject。当然,您可以在任何地方传递 QObject* 和 MyInterface*,但这也很麻烦。 - Dan Milburn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接