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

Ros*_*ers 4 qt qml

我正在尝试在 QML 和 Qt C++ 中创建类似jQuery 的自动完成功能的小部件。为此,我创建了一个 C++AutoCompleteListener子项QObject,然后将其注册为:

qmlRegisterType<AutoCompleteListener>(
    "foo.AutoCompleteListener",0,1,"AutoCompleteListener");
Run Code Online (Sandbox Code Playgroud)

然后,我实例化侦听器AutoCompleteForm等:

import QtQuick 2.5
import com.foo.AutoCompleteListener 0.1

Item {
    AutoCompleteForm { id: autocomplete_form }
    AutoCompleteListener { id: listener }
}
Run Code Online (Sandbox Code Playgroud)

如何传递到QML对象的引用AutoCompleteFormAutoCompleteListener

我尝试将autocomplete_form字段传递给:

Q_INVOKABLE void set_autocomplete_form(QQmlComponent *autocomplete_form);
Run Code Online (Sandbox Code Playgroud)

关于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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,参考是nullptr即使两个AutoCompleteListenerAutoCompleteForm已实例:

Instantiating AutoCompleteListener and parent is  QObject(0x0)
qml: AutoCompleteListener completed
qml: AutoCompleteForm completed
Setting autocomplete_form =  QObject(0x0)
Run Code Online (Sandbox Code Playgroud)

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

QObject* f = mView.rootObject();->findChild<QObject *>("AutoCompleteForm");
Run Code Online (Sandbox Code Playgroud)

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

Ari*_* M. 5

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

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

另外,我认为您的问题是关于XY 问题。你有一个问题X并且你认为Y解决了它,所以你要求Y

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

我正在尝试在 QML 和 Qt C++ 中创建类似 jQuery 的自动完成功能的小部件。

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

AutocompleteForm{
    id: form
    text: "Search here..."
    suggestedTerms: helper.results
}
AutoCompleteHelper{
    id: helper
    searchFor: form.text
}
Run Code Online (Sandbox Code Playgroud)

而对于 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;
};
Run Code Online (Sandbox Code Playgroud)

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

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