【问题标题】:How to catch a signal emitted from derived c++ class in QML?如何在 QML 中捕获派生的 c++ 类发出的信号?
【发布时间】:2015-05-13 18:21:26
【问题描述】:

我的模型是 C++,前端是 QML。该模型由一个包含其他组件的接口类组成。简化形式(概念验证阶段) 这个接口类是纯虚拟类,称为Base,它派生自QObject。我有一个从Base 派生的Derived

当数据发生变化时,我在派生类中发出信号。我的问题是如何在 QML 中捕捉到这个信号和过程?

derived.obj:-1: error: LNK2019: unresolved external symbol "public: void __thiscall Derived::somethingChanged(void)" (?somethingChanged@Derived@@QAEXXZ) referenced in function "public: virtual void __thiscall Derived::doSomething(void)" (?doSomething@Derived@@UAEXXZ)

我的 Base.h 类是:

#include <QObject>

class Base : public QObject
{
    Q_OBJECT
public:
    explicit Base(QObject *parent = 0);
    ~Base();

    virtual void doSomething() = 0;

signals:

public slots:
};

Derived.h 是

#include "base.h"

class Derived : public Base
{
    Q_OBJECT
public:
    Derived();
    ~Derived();

    virtual void doSomething();

signals:
    void somethingChanged();
};

Derived.cpp 是

#include "derived.h"

#include <QDebug>

Derived::Derived()
{

}

Derived::~Derived()
{

}

void Derived::doSomething()
{
    qDebug() << "doSomething() called in Derived";

    emit somethingChanged(); // this doesn't compile!
}


Connections {
    target: What? // what should I put here, 
    onSomethingChanged: console.log("The application data changed!")
}

同样的问题是我为target 属性添加了什么?该模型只会将接口类公开给 qml,即Base 类,但信号实际上是在派生类中发出的。信号是否也应该是虚拟的?我应该如何在 QML 中接收这个信号?

【问题讨论】:

  • 您将 Derived 实例作为目标。 (另外你忘记了 Derived 的 Q_OBJECT 宏)
  • @FrankOsterfeld 但是派生类是模型的内部部分,它没有直接暴露,但也许我需要暴露它?

标签: qt qml


【解决方案1】:

MOC 是实现功能(您的信号)void somethingChanged(); 的人。

moc_XYZ.cpp 文件中的示例可能如下所示。

// SIGNAL 13
void Derived::doSomething()
{
    QMetaObject::activate(this, &staticMetaObject, 13, Q_NULLPTR);
}

那么如何让 MOC 开心呢?

在您的derived.h 中添加Q_OBJECT

【讨论】:

    【解决方案2】:

    为了创建要在 Qt 中使用的接口,我发现了两种情况:

    1. 基于QObject

    这是最简单的形式,而且你的方法是正确的。只需使用抽象方法创建一个基于 QObject 的类并声明信号。派生类不得再次声明信号,只需在需要时发出即可。

    这是你的情况。 MOC生成器需要知道Base接口有信号,可以发射。只需在 Base 中声明信号而不是派生类。

    1. 纯虚拟类(额外信息)

    有时您需要从任何基于 QObject 的类(例如 QAbstractListModel)派生,但它也需要实现一些接口。 C++ 允许多重继承,但 Qt 不喜欢从两个或多个基于 QObject 的类派生的类。 因此,您应该创建一个 plain 纯虚拟类,并将信号声明为任何其他未实现的方法。

    // Base  
    class Base
    {
    public:
        Base();
        virtual ~Base(); 
    
        virtual void doSomething() = 0;
    
    signals:
        virtual void somethingChanged() = 0;
    
    };
    

    现在,从 Base 派生并再次声明信号:

    // Derived
    class Derived : public QObject, public Base
    {
        Q_OBJECT
    public:
        explicit Derived(QObject *parent = 0);
        ~Derived();
    
        //Implmetations of Base methods
    public:
        void doSomething();
    
        //Declaration of Base signals
    signals:
        void somethingChanged();
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多