I'm trying to implement some sort of custom Menu with custom elements. The ultimate goal is to create some sort of popup menu with text and icons. But during creation I faced with some issues. I can show 2 primary problems:
- There is a strange menu element with title
Hello world
at the first position (looks like it's read title of application window):
- From time to time I'm getting errors like
qrc:/BreezeQuickMenu.qml:45: TypeError: Property 'clicked' of object QQuickListView(0x1120830) is not a function
Here is my actual code:
main.qml
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.2
ApplicationWindow {
title: qsTr("Hello World")
width: Screen.width
height: Screen.height
visible: true
id: win
color: brPalette.normalBackground
BreezeQuickMenu{
id: brMenu
x: 490
y: 199
width: 128
height: 256
palette: brPalette
menuFont.pointSize: 16
BreezeQuickMenuItem{
title: "Item 1"
onClicked: mbox.show()
}
BreezeQuickMenuItem{
title: "Item 2"
}
BreezeQuickMenuItem{
title: "Item 3"
}
}
}
BreezeQuickMenu.qml
import QtQuick 2.4
Item {
id: root
property BreezeQuickPalette palette: BreezeQuickPalette
property alias currentIndex: menuList.currentIndex
property font menuFont
property bool menuVisible: false
implicitWidth: 128
implicitHeight: menuList.height
ListView{
id: menuList
anchors.fill: parent
model: root.children
clip: true
delegate: Component {
id: menuItem
Rectangle {
id: menuElement
property bool isCurrentItem: ListView.isCurrentItem
anchors {
left: parent.left
right: parent.right
}
color: palette.normalBackground
height: menuText.font.pixelSize*1.2
Text {
id: menuText
anchors.fill: parent
text: title
color: palette.normalText
font: menuFont
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onClicked: {
menuList.currentIndex = index
menuList.model[index].clicked()
}
}
}
}
}
}
BreezeQuickMenuItem.qml
import QtQuick 2.4
Item {
id: root
property string title: "Menu Element"
signal clicked
}
As you can see I'm trying to implement menu list and menu items with their own signals. I have 2 questions:
how can I properly get rid of using title property of parent element, since I need to read title property of childrens
what is the correct approach of using signals and slots in menu elements to avoid above error?
Please help me to understand. Full project can be pulled here:
git clone git://git.code.sf.net/p/breezequick/code breezequick-code
The problem with the
signal
is related to its declaration. Signals are always declared as a function would be: with a signature. In other words, asignal
without parameters has the formThat's also why you got the error "
is not a function
". Apart from that, the usage of signals/signal handlers is correct. Anyhow, reading carefully the documentation wouldn't hurt. This page covers in detail the argument.Coming to the other problem, you made the wrong assumption: anything that is declared inside a component is part of the
children
of the component itself. Here you declared aBreezeQuickMenu
which has a childListView
. When you use it and add theBreezeQuickMenuItem
s, you add them to the same set to which theListView
belongs. In the end you have four elements in thechildren
property. Also, by adding theListView
to itself through themodel
you mess up things to the point that a totally unrelated string is rendered.There are several ways to handle
Items
as model members for a view, inclusingVisualItemModel
and using object Instanced as models. However, by skimming your code, it is clear that you want to define a component which adds menu items in a declarative fashion. Usingchildren
is not sufficient in this case. You also need thedefault
property:Hence you can define the
default
property for yourBreezeQuickMenu
and exploit it to obtain the desiredchildren
for your list. A common approach would be the following (code simplified):The basic idea is to exploit also property
alias
: basically in (1) we are saying that "all theItem
s declared insideBreezeQuickMenu
are automaticallychildren
ofaddItem
which is an inner declaredItem
(2). In this way theListView
is kept apart whereas all theBreezeQuickMenuItem
are gathered together, underaddItem
children
property. At this point, it is sufficient to use the samechildren
property as themodel
(3) for theListView
and that's it.