我正在尝试使用自定义元素实现某种自定义菜单。最终目标是创建一些带有文本和图标的弹出菜单。但在创作过程中我遇到了一些问题。我可以展示两个主要问题:
Hello world
的奇怪菜单元素(看起来像是读取应用程序窗口的标题):
qrc:/BreezeQuickMenu.qml:45: TypeError: Property 'clicked' of object QQuickListView(0x1120830) is not a function
这是我的实际代码:
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
}
正如您所看到的,我正在尝试使用自己的信号实现菜单列表和菜单项。我有两个问题:
如何正确摆脱使用父元素的title属性,因为我需要读取子元素的title属性
在菜单元素中使用信号和插槽以避免上述错误的正确方法是什么?
请帮我理解。完整的项目可以在这里拉出来:
git clone git://git.code.sf.net/p/breezequick/code breezequick-code
答案 0 :(得分:3)
signal
的问题与其声明有关。信号总是被声明为一个函数:带有签名。换句话说,没有参数的signal
具有
signal <signal_name>()
这也是您收到错误&#34; is not a function
&#34;的原因。除此之外,信号/信号处理器的使用是正确的。无论如何,仔细阅读文档不会有什么坏处。 This page详细介绍了论点。
回到另一个问题,你做了一个错误的假设:在组件中声明的任何东西都是组件本身的children
的一部分。在这里,您声明了BreezeQuickMenu
,其中有一个孩子ListView
。当您使用它并添加BreezeQuickMenuItem
时,您可以将它们添加到ListView
所属的相同集中。最后,您在children
属性中有四个元素。另外,通过ListView
将model
添加到本身,你会搞砸到完全不相关的字符串呈现的点。
有几种方法可以将Items
作为视图的模型成员来处理,包含VisualItemModel
和使用object Instanced as models。但是,通过略读代码,很明显您要定义一个以声明方式添加菜单项的组件。在这种情况下,使用children
是不够的。您还需要default
属性:
对象定义可以具有单个默认属性。默认属性是如果在另一个对象的定义中声明对象而未将其声明为特定属性的值,则为其赋值的属性。
因此,您可以为default
定义BreezeQuickMenu
属性,并利用它来获取列表所需的children
。一种常见的方法是以下(代码简化):
import QtQuick 2.4
Item {
id: root
property BreezeQuickPalette palette: BreezeQuickPalette
property alias currentIndex: menuList.currentIndex
// default declaration (1)
default property alias contents: addItem.children
// Item to which the inner declared meantime will belong (2)
Item {
id: addItem
}
property font menuFont
property bool menuVisible: false
implicitWidth: 128
implicitHeight: menuList.height
ListView{
id: menuList
anchors.fill: parent
model: contents // usage of the default property (3)
clip: true
delegate: Rectangle {
// your current delegate code
}
}
}
基本思想也是利用property alias
:基本上在(1)中我们说&#34;在Item
内声明的所有BreezeQuickMenu
都是children
} addItem
这是一个内部声明Item
(2)。通过这种方式,ListView
保持分开,而所有BreezeQuickMenuItem
在addItem
children
属性下聚集在一起。此时,对children
使用与model
(3)相同的ListView
属性就足够了。