I have 2 qml files. Toolbarbutton.qml creates a button and DockWidget.qml creates a ListView. I am trying to have the button in Toolbarbutton broadcast to DockWidget that the button has been clicked. I then want to add items to my listView.
I have been trying to use a signal to establish the communication. In the Toolbarbutton.qml, I have a Rectangle item with an ID of saveButton. Under this Rectangle Item I added a signal called addSaveHistory(). I have shortened the code so its easier to see what I am doing.
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
}
}
}
In the DockWidget.qml file I have an Item that is using the Connections component. I have shorten the code so its easier to see what I am doing.
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
}
}
}
I can't seem to figure out why the onAddSaveHistory is never called. I have also tried using a Loader component to load the Dockwidget.qml file into Toolbarbutton.qml and then specifically call a function in Dockwidget, but that doesn't work as well.
Do I just have the wrong idea of how the signals should work? I would greatly appreciation any guidance.
Here is my main.qml file.
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")
}
}
First of all, realise that the signal is declared on the QML element at the root of the ToolbarButton.qml file, i.e. the Rectangle. Only the root item forms the interface for the QML element. All child elements are hidden to the outside world. So it's customary to declare the signal near the top of the file. A common ordering is:
Item {
id: root
property real foo: 0.0
property alias bar: innerItem.bar
signal baz(url location)
Rectangle {
id: innerItem
property color bar: "red"
}
}
So in this case a simple ToolbarButton.qml that declares a signal and emits it when you click in a contained MouseArea would look like this:
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?")
}
}
}
Then a simple consumer of this signal, here just a Text element but can be anything might look like this:
import QtQuick 2.3
Text {
id: dockWidget
text: "Waiting for a click..."
}
But wait, you say, how does that help. Well so far there is no connection. We make that when we instantiate our reciever item. So here, the main.qml file looks like this:
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"
}
}
}
In actual fact there is no need for the Connections element to be a child of the DockWidget. Think of the ToolbarButton and Dock widget as lego bricks that we are plumbing together at a location that has a higher level of knowledge about these items and how they should interact. If you want to though, you could wrap this up into its own more complicated custom QML component.
Furthermore, if you only have one thing caring about the signal, you don't even need the Connections element at all:
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
}
}
Hope this helps.