【问题标题】:QML send signals between anonymous grandchildrenQML 在匿名孙子之间发送信号
【发布时间】:2016-06-12 19:39:19
【问题描述】:

我正在尝试在树结构中的 qml 组件之间进行通信。我有一个 main.qml 组件,其 id 为 root。它有两个孩子,每个孩子都有任意数量的从转发器和模型动态创建的孩子。

当点击其中一个孙子时,我希望其他人知道并能够采取行动。所以如果我可以在孙子之间发送信号就好了。

问题是它们都没有设置 id 属性,因为它们是动态生成的,并且其中一些位于不同的范围内。为了在他们之间进行交流,我做了以下事情: 在 root 中创建了一个函数,每个孙子都可以看到,并且可以使用消息作为参数调用它。然后根函数会发出一个带有消息作为参数的信号。所有的孙子都可以连接到信号,因为他们知道 root 的 id。

人们对此有何看法?我感觉我错过了 qml 中的信号点,感觉就像我实现了一个粗略的系统并且错过了整个点或其他东西。

另外,我想远离 C++ 世界,但人们是否认为最好使用 C++ 类以便我可以使用信号和插槽。

我的目标是一个耦合非常松散的 MVC 结构和一个集中式控制器。人们如何看待 MVC 中 QML 组件之间的通信。

我在这里发现的唯一类似问题是关于 C++ 或在组件上使用硬编码的 id。

我认为 id 不能动态设置,甚至在创建时也不能;我错了吗?

另外,组件在不同的范围内,所以无法解析 id;我错了吗?

我已经写了一些代码:

//qml.main
import QtQuick 2.4
import QtQuick.Controls 1.3

ApplicationWindow {
    id: root
    visible: true
    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: console.log("Open action triggered");
            }
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
    }

    property string thisName: "root"

    signal rootSays(string broadcastMessage)

    function callRoot(message) {
        var response = message
        print("Root received: " + message)
        print("Root broadcasting: " + response)
        rootSays(response)
    }

    MajorComponent{//this is root's child A
        property string thisName: "A"
        thisModel: [{name:"First Grandchild of A", color:"red", y:0},
                    {name:"Second Grandchild of A", color:"green", y:80}]
    }

    MajorComponent{//this is root's child B
        property string thisName: "B"
        thisModel: [{name:"First Grandchild of B", color:"blue", y:210},
                    {name:"Second Grandchild of B", color:"yellow", y:290}]
    }


}


//qml.MinorComponent
import QtQuick 2.0

Rectangle {
    property string thisName: ""
    property string thisColor: ""

    color: thisColor
    height: 50; width: 200
    Text {
        anchors.centerIn: parent
        text: thisName
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            print(thisName + " clicked")
            print("Root called with: " + thisName)
            root.callRoot("Hello from " + thisName)
            print("---")
        }
    }
}


//qml.MajorComponent
import QtQuick 2.0

Rectangle {
    property var thisModel: []

    Repeater {
        model:thisModel
        MinorComponent {
            y: modelData.y
            thisName: modelData.name
            thisColor: modelData.color
            function handleResponse(response) {
                print(thisName + " received: " + response);
            }
            Connections {
                target: root
                onRootSays: handleResponse(broadcastMessage)
            }

        }
    }

}

【问题讨论】:

  • 这是一个有趣的问题,但要回答它,有一些可用的代码会更容易,我们可以使用和测试。我的意思是,有人可能会直接给你答案,但是对于像 QML 这样的特定问题,并且考虑到 Qt 在 QML 中的错误或实现细节的跟踪记录,拥有一些代码会容易得多。
  • 将控制器作为 C++ 公开对象有什么问题?
  • @peppe 这有什么帮助?
  • 你可能会觉得这个读起来很有趣:medium.com/@benlaud/…我以一种简化的方式使用这个模式,我直接监听 AppActions
  • 因为一旦您的应用程序增长,您就需要将大孙子的事物连接到其他大孙子。这需要集中式设计,这在 C++ 中更容易。 (或通过 QML 中的pragma Singleton

标签: qt qml


【解决方案1】:

我认为 id 不能动态设置,甚至在创建时也不能; 我错了吗?

ids 纯粹是“编译”时构造。话虽如此,没有什么能阻止您实施和管理自己的对象注册系统。一个简单的空 JS 对象就可以了,它可以有效地用作 QMap 根据键(属性名称)查找对象。如果您将地图对象设置为根对象的属性,由于动态范围,它应该可以从树中的每个对象中解析。

使用信号的方法是一种可靠的 IMO。我使用了类似的东西,结合仿函数和引用捕获,允许访问任意树结构中的任意和可选的现有对象,通过他们必须满足的各种标准过滤候选对象。你可以用这种技术做一些非常棘手的事情。

话虽如此,一个说明您实际想要实现的目标的实际示例将有助于提供更具体的答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多