如何将QML对象引用传递给Qt C ++?

时间:2015-11-30 19:32:34

标签: qt qml

我试图在QML和Qt C ++中创建像jQuery's autocomplete这样的小部件。为此,我创建了一个AutoCompleteListener的C ++ QObject子项,然后将其注册为:

qmlRegisterType<AutoCompleteListener>(
    "foo.AutoCompleteListener",0,1,"AutoCompleteListener");

然后,我实例化了监听器和AutoCompleteForm,如:

import QtQuick 2.5
import com.foo.AutoCompleteListener 0.1

Item {
    AutoCompleteForm { id: autocomplete_form }
    AutoCompleteListener { id: listener }
}

如何将对QML对象AutoCompleteForm的引用传递给AutoCompleteListener

我尝试将autocomplete_form字段传递到:

Q_INVOKABLE void set_autocomplete_form(QQmlComponent *autocomplete_form);

onCompleted信号上:

Item {
    AutoCompleteForm {
        id: autocomplete_form
        Component.onCompleted: {
            console.log("AutoCompleteForm completed");
            listener.set_autocomplete_form(autocomplete_form);
        }
    }
    AutoCompleteListener {
        id: listener
        Component.onCompleted: {
            console.log("AutoCompleteListener completed");
        }
    }
}

但是,即使nullptrAutoCompleteListener都已实例化,引用也是AutoCompleteForm

Instantiating AutoCompleteListener and parent is  QObject(0x0)
qml: AutoCompleteListener completed
qml: AutoCompleteForm completed
Setting autocomplete_form =  QObject(0x0)

如何获得对AutoCompleteFormAutoCompleteListener的QML父级的引用?我想避免使用以下内容爬下整个QML层次结构:

QObject* f = mView.rootObject();->findChild<QObject *>("AutoCompleteForm");

我计划支持并行实例化多个AutoComplete小部件,因此操纵QML对象的相对路径(../AutoCompleteForm)似乎比必须爬过树更好。

3 个答案:

答案 0 :(得分:3)

  

如何将QML对象引用传递给Qt C ++?

你不能,该语言不是为此而设计的。但您可以使用findChild和findChildren从C ++中获取引用。但请阅读下面的真实解决方案。

此外,我认为您的问题是 XY Problem 。你有一个问题 X ,你认为 Y 解决了它,所以你要求 Y

针对原始问题的正确解决方案:

  

我正在尝试创建像jQuery的自动完成一样的东西   QML和Qt C ++中的小部件。

要解决真正的问题,您需要正确使用属性绑定。 QML是一种声明性语言,对命令式编程的自我痴迷使得很难直截了当。 将此模式用于QML:

AutocompleteForm{
    id: form
    text: "Search here..."
    suggestedTerms: helper.results
}
AutoCompleteHelper{
    id: helper
    searchFor: form.text
}

对于C ++实现

class AutoCompleteHelper : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString searchFor   READ searchFor WRITE setSearchFor NOTIFY searchForChanged)
    Q_PROPERTY(QStringList results READ results                      NOTIFY resultsChanged)
public:
    AutoCompleteHelper() {}
    virtual ~AutoCompleteHelper() {}
    QString searchFor() const { return m_searchFor; }
    QStringList results() const { return m_results; }

public slots:
    void setSearchFor(QString searchFor)
    {
        if (m_searchFor == searchFor)
            return;
        m_searchFor = searchFor;
        emit searchForChanged();

        // 1. Search for it...
        // 2. Some time later fill m_results
        // 3. Then: emit resultsChanged()
    } 
signals:
    void searchForChanged();
    void resultsChanged();

private:

    QString m_searchFor;
    QStringList m_results;
};

然后你会看到它神奇地起作用,因为一旦你改变了form.text,绑定就会在helper.searchFor中设置值,然后立即触发C ++插槽,你甚至可以瞬间做出反应,在C ++中放射of resultsChanged()神奇地填充form.suggestedTerms。

您会发现此模式非常高效,因此您甚至希望通过在C ++中重新启动计时器来延迟它。此外,它还具有精美的陈述性和清洁性。

答案 1 :(得分:1)

  

如何获取对AutoCompleteForm的引用或   AutoCompleteListener的QML父级?

rootObject() - &gt; findChild()的唯一替代方法似乎是QQmlProperty::read。有几个read()函数重载,因此您可以更精确地指定上下文。您必须提供要获取的对象的名称,并使其成为某个根对象的属性。我喜欢关于QML和C ++之间接口这一主题的一般article

要准确完成您想要的内容或访问某些已知属性的父级,您可以尝试QQmlContext::parentContextQQmlProperty::read一起接受上下文,然后查看空对象名称是否允许解析该对象。

答案 2 :(得分:0)

您可以将其作为QVariant传递:

Q_INVOKABLE void QmlLink::pass_object(QVariant v)
{
    YourObject* tempObject = (YourObject*) v.value<void *>();

    ...
}

qml:

my_bound_property.pass_object(the_object);