无法获取 2 个 QML 文件以使用信号进行通信

Trouble getting 2 QML files to communicate using Signals

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

我一直在尝试使用信号来建立通信。在 Toolbarbutton.qml 中,我有一个 ID 为 saveButton 的矩形项。在这个矩形项下,我添加了一个名为 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 文件中,我有一个使用连接组件的项目。我缩短了代码,以便更容易看到我在做什么。

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")

  }
}

首先,意识到信号是在 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
    }
}

希望对您有所帮助。