【问题标题】:Trouble getting 2 QML files to communicate using Signals无法使用 Signals 获取 2 个 QML 文件进行通信
【发布时间】:2016-08-06 05:08:49
【问题描述】:

我有 2 个 qml 文件。 Toolbarbutton.qml 创建一个按钮,DockWidget.qml 创建一个 ListView。我试图让 Toolbarbutton 中的按钮向 DockWidget 广播该按钮已被单击。然后我想将项目添加到我的 listView 中。

我一直在尝试使用信号来建立通信。在 Toolbarbutton.qml 中,我有一个 ID 为 saveButton 的 Rectangle 项。在这个 Rectangle Item 下,我添加了一个名为 addSaveHistory() 的信号。我已经缩短了代码,以便更容易看到我在做什么。

Rectangle {
 id: saveButton
 width: 50
 height: 30
 border.color: "white"
 color: buttonMouseArea.containsMouse ? "grey" : "black"

//Button text
Text{
    id: buttonLabel
    anchors.centerIn: parent
    text: "Save +"
    color: "white"
}
signal addSaveHistory(string url)

 MouseArea{
    id: buttonMouseArea
    anchors.fill: parent //anchor the mousearea to the rect area

    //onClicked handles valid mouse button clicks
    onClicked: {
       addSaveHistory("Hello?") //dispatch the event

    }
}
}

在 DockWidget.qml 文件中,我有一个使用 Connections 组件的项目。我已经缩短了代码,因此更容易看到我在做什么。

Item{
  width: 100
  height: 100
  objectName: "Save + History"

 Rectangle {
   id: rect
   anchors.fill: parent
   color: "#323232"

 Connections {
     target: saveButton //id of rectangle in ToolbarButton.qml

     onAddSaveHistory: {

       // this is never called  
     }
 }
}

我似乎无法弄清楚为什么永远不会调用 onAddSaveHistory。我也尝试过使用 Loader 组件将 Dockwidget.qml 文件加载到 Toolbarbutton.qml 中,然后专门调用 Dockwidget 中的函数,但这也不起作用。

我对信号应该如何工作有错误的想法吗?我将不胜感激任何指导。

这是我的 main.qml 文件。

import QtQuick 2.2
import Painter 1.0

import "save.js" as Save

Plugin {

//executed at startup
Component.onCompleted:{

  //add toolbar
  alg.ui.addToolBarWidget("ToolbarButton.qml")//add a button to toolbar
  alg.ui.addDockWidget("DockWidget.qml")//add dock widget

  Save.log("Incremental Save Plugin has been created")

  }
}

【问题讨论】:

    标签: qt qml signals-slots


    【解决方案1】:

    首先,意识到信号是在 ToolbarButton.qml 文件根目录的 QML 元素上声明的,即 Rectangle。只有根项构成 QML 元素的接口。所有子元素都对外界隐藏。所以习惯上在文件顶部附近声明信号。一个常见的顺序是:

    Item {
        id: root
        property real foo: 0.0
        property alias bar: innerItem.bar
        signal baz(url location)
    
        Rectangle {
            id: innerItem
            property color bar: "red"
        }
    }
    

    所以在这种情况下,一个简单的 ToolbarButton.qml 声明一个信号并在您单击包含的 MouseArea 时发出它,如下所示:

    import QtQuick 2.3
    
    Rectangle {
        id: root
        width: buttonLabel.width + 20
        height: buttonLabel.height + 20
        color: "steelBlue"
    
        // Declare signal on the button object
        signal addSaveHistory(string url)
    
        Text {
            id: buttonLabel
            anchors.centerIn: parent
            text: "Save +"
        }
    
        MouseArea {
            id: buttonMouseArea
            anchors.fill: parent
            onClicked: {
                // emit the signal
                root.addSaveHistory("Hello?")
            }
        }
    }
    

    然后是这个信号的简单消费者,这里只是一个文本元素,但可以是任何东西,可能看起来像这样:

    import QtQuick 2.3
    
    Text {
        id: dockWidget
        text: "Waiting for a click..."
    }
    

    但是等等,你说,这有什么帮助。好吧,到目前为止没有任何联系。当我们实例化我们的接收者项目时,我们会这样做。所以在这里,main.qml 文件看起来像这样:

    import QtQuick 2.3
    import QtQuick.Window 2.2
    
    Window {
        visible: true
    
        // Instantiate the ToolbarButton that emits the signal when clicked
        ToolbarButton {
            id: toolbarButton
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.topMargin: 10
            anchors.leftMargin: 10
        }
    
        // Instantiate the DockWidget (just a Text element in this example)
        DockWidget {
            id: dockWidget
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 10
            anchors.left: parent.left
            anchors.leftMargin: 10
    
            // Complete the plumbing that connects the signal from item above
            // with id: toolbarButton.
            Connections {
                target: toolbarButton
                // When signal addSaveHistory is emitted,
                // replace binding above with a new one
                onAddSaveHistory: dockWidget.text = "Button was clicked"
            }
        }
    }
    

    事实上,Connections 元素不需要是 DockWidget 的子元素。将 ToolbarButton 和 Dock 小部件想象成乐高积木,我们在一个对这些项目以及它们应该如何交互具有更高水平的知识的位置进行管道连接。但是,如果您愿意,可以将其包装到它自己的更复杂的自定义 QML 组件中。

    此外,如果你只关心信号的一件事,你甚至根本不需要 Connections 元素:

    import QtQuick 2.3
    import QtQuick.Window 2.2
    
    Window {
        visible: true
    
        ToolbarButton {
            id: toolbarButton
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.topMargin: 10
            anchors.leftMargin: 10
    
            // Add signal handler directly to emitter
            onAddSaveHistory: dockWidget.text = "Button was clicked"
        }
    
        DockWidget {
            id: dockWidget
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 10
            anchors.left: parent.left
            anchors.leftMargin: 10
        }
    }
    

    希望这会有所帮助。

    【讨论】:

    • 嗨,肖恩,非常感谢您的帮助。我有一个独特的问题,因为我正在使用 qml 为另一个使用 qml 创建接口的应用程序创建插件。我无法按照您的建议设置我的 main.qml。这就是我的 main.qml 需要格式化的方式。我编辑了我的原始帖子以显示 main.qml。
    • 我编辑了 ToolbarButton.qml 以按照您的建议工作,以便将其放置在矩形项下,然后使用 id.signalFucntion() 语法调用信号。但是,我试图建立的连接似乎不知道 ToolbarButton.qml 中的信号
    • 没有看到 alg.ui.addToolBarWidget() 和 alg.ui.addDockWidget() 做什么很难说解决方案是什么。我猜他们实例化了作为参数传入的 QML 文件。不知何故,您需要能够引用那些能够在 Plugin {} 范围内使用 Connections {} 元素。您可能需要查看这些函数的文档(我还找不到任何公开的文档)或询问编写它们的开发人员是否有典型示例。
    • 如果幸运的话,这些函数将返回对创建的 ToolbarButton 的引用,然后您可以将其存储在您在插件上声明的属性中。 DockWidget 也是如此。所以它可能是这样的: Plugin { id: root;属性变量按钮:空;属性 var dockWidget: null; Component.onCompleted: { root.button = alg.ui.addToolbarWidget(...); root.dockWidget = alg.ui.addDockWidget(...);但这取决于这些函数是否返回任何有用的东西(你希望它们会)。如果没有,那么您需要一些其他 API 才能引用创建的项目。
    • 谢谢肖恩。我明白你的意思:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 2015-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多