Вызов метода C из QML

#qt #qml #qtquick2

#qt #qml #qtquick2

Вопрос:

ВОТ ПРОЕКТ Qt с минимальным скелетом, чтобы показать, в чем проблема (проверьте консоль после запуска этого проекта)
http://uloz.to/xqxrXpdL/qtproject-zip

Я пытаюсь вызвать общедоступный слот из qml

 Component.onCompleted: print(model.activate())
  

Все еще получаю ошибку:

 TypeError: Property 'activate' of object QQmlDMObjectData(0x7fa35dd89eb0) is not a function
  

Если бы я попытался вызвать метод динамически из C , он работает:

 auto item = new TreeItem<MainMenuItem>(new MainMenuItem("kyklop"));

QMetaObject::invokeMethod(item, "activate");
  

Если я попытаюсь получить доступ к обычному свойству моего класса TreeItemTemplateBackend из qml (для уровня экземпляра), это сработает, поэтому проблема возникает только при вызове метода. Я думаю, что это может быть что-то с этим подклассом / шаблонным классом.

Регистрация в qml:

 qmlRegisterType<TreeItemTemplateBackend>("engine.ui", 1, 0, "TreeItemTemplateBackend");
qmlRegisterType<TreeItem<InspectorItem>>("engine.ui", 1, 0, "InspectorTreeItem");
qmlRegisterType<TreeItem<MainMenuItem>>("engine.ui", 1, 0, "MainMenuTreeItem");
  

TreeItem.h

 #ifndef TREEITEM_H
#define TREEITEM_H

#include <QObject>
#include "TreeItemTemplateBackend.h"

template <typename T>
class TreeItem :  public TreeItemTemplateBackend
{

public:
    explicit TreeItem(QObject * parent = NULL);
    explicit TreeItem(T * data, QObject * parent = NULL);
    explicit TreeItem(TreeItem<T> amp; other);
    void addChild(TreeItem<T> * child);
    ~TreeItem() {}
};

#endif // TREEITEM_H
  

TreeItemTemplateBackend.h

 #ifndef TREEITEMTEMPLATEBACKEND_H
#define TREEITEMTEMPLATEBACKEND_H

#include <QList>
#include <QQmlListProperty>

class TreeItemTemplateBackend : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QObject * data READ data WRITE setData NOTIFY dataChanged)
    Q_PROPERTY(QQmlListProperty<TreeItemTemplateBackend> childs READ childs NOTIFY childsChanged)
    Q_PROPERTY(int level READ level WRITE setLevel NOTIFY levelChanged)
public:
    explicit TreeItemTemplateBackend(QObject * parent = NULL);
    QObject * data() const;
    void setData(QObject * data);
    QQmlListProperty<TreeItemTemplateBackend> childs() const;
    void addChild(TreeItemTemplateBackend * child);
    int level() const;
    void setLevel(int level);
    void dump(QString propertyName) const;
    ~TreeItemTemplateBackend() {}
signals:
    void activated(); 
    void dataChanged();
    void childsChanged();
    void levelChanged();
public slots:
    void activate(); // this is what i am trying to call
protected:
    QObject * m_data;
    QList<TreeItemTemplateBackend *> m_children;
    int m_level;
    static void append_function(QQmlListProperty<TreeItemTemplateBackend> * property, TreeItemTemplateBackend * item);
    static TreeItemTemplateBackend * at_function(QQmlListProperty<TreeItemTemplateBackend> * property, int index);
    static void clear_function(QQmlListProperty<TreeItemTemplateBackend> * property);
    static int count_function(QQmlListProperty<TreeItemTemplateBackend> * property);
};

#endif // TREEITEMTEMPLATEBACKEND_H
  

Комментарии:

1. Зарегистрирован ли ваш пользовательский тип в движке QML?

2. @ddriver: да, это так, я изменил код, чтобы показать регистрацию

3. Можете ли вы предоставить компилируемый пример? Например, один main.cpp а файл QML?

4. @Mitch: я опубликую zip-файл с проектом, который я создал (он содержит только минимум, чтобы показать проблему)

5. Я не уверен, но это, вероятно, связано с шаблоном. Почему бы вам не попробовать отказаться от шаблона и использовать QVariant вместо T * для данных и зарегистрировать необходимые типы в метасистеме. Также взгляните на эту ссылку: doc.qt.digia.com/qq/qq15-academic.html

Ответ №1:

QQmlDMObjectData является оболочкой для фактического объекта, используемого в делегатах. Исходный объект доступен через свойство modelData , поэтому model.modelData.activate() должен работать.

Ответ №2:

Если вы вызываете для него «метод», и все же вы используете его как метод, поэтому преобразуйте его в метод:

 ...
public:
void Q_INVOKABLE activate();
...