菜单元素的 ListView 信号和槽
ListView signals and slots for menu elements
我正在尝试使用自定义元素实现某种自定义菜单。最终目标是创建某种带有文本和图标的弹出菜单。但是在创作过程中我遇到了一些问题。我可以展示 2 个主要问题:
- 第一个位置有一个标题为
Hello world
的奇怪菜单元素(看起来是阅读应用程序 window 的标题):
- 有时我会收到类似
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
}
如您所见,我正在尝试使用它们自己的信号来实现菜单列表和菜单项。我有 2 个问题:
我怎样才能正确地摆脱使用 title 属性 of parent 元素,因为我需要阅读 title 属性 of childrens
在菜单元素中使用信号和槽以避免上述错误的正确方法是什么?
请帮助我理解。完整的项目可以在这里拉取:
git clone git://git.code.sf.net/p/breezequick/code breezequick-code
signal
的问题与其声明有关。信号总是被声明为函数:带有签名。换句话说,没有参数的 signal
的形式是
signal <signal_name>()
这也是您收到错误“is not a function
”的原因。除此之外, signals/signal 处理程序的用法是正确的。无论如何,仔细阅读文档不会有什么坏处。 This page 详细介绍了论点。
谈到另一个问题,您做出了错误的假设:在组件 内声明的任何内容都是组件本身 children
的 部分。在这里你声明了一个 BreezeQuickMenu
它有一个 child ListView
。当您使用它并添加 BreezeQuickMenuItem
时,您将它们添加到 ListView
所属的 相同的 集中。最后,children
属性 中有 四个 个元素。此外,通过 model
将 ListView
添加到 自身 中,你会把事情搞得一团糟,以至于呈现完全不相关的字符串。
有几种方法可以将 Items
处理为视图的模型成员,包括 VisualItemModel
and using object Instanced as models。但是,通过浏览您的代码,很明显您想要定义一个以声明方式添加菜单项的组件。在这种情况下使用 children
是不够的。您还需要 default
属性:
An object definition can have a single default property. A default property is the property to which a value is assigned if an object is declared within another object's definition without declaring it as a value for a particular property.
因此您可以为您的 BreezeQuickMenu
定义 default
属性 并利用它为您的列表获得所需的 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) 中我们说“在 BreezeQuickMenu
中声明的所有 Item
都自动 children
addItem
的内部声明 Item
(2)。通过这种方式,ListView
保持分开,而所有 BreezeQuickMenuItem
聚集在一起,在 addItem
下children
属性. 此时,对 ListView
和 model
(3) 使用相同的 children
属性 就足够了就是这样。
我正在尝试使用自定义元素实现某种自定义菜单。最终目标是创建某种带有文本和图标的弹出菜单。但是在创作过程中我遇到了一些问题。我可以展示 2 个主要问题:
- 第一个位置有一个标题为
Hello world
的奇怪菜单元素(看起来是阅读应用程序 window 的标题):
- 有时我会收到类似
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
}
如您所见,我正在尝试使用它们自己的信号来实现菜单列表和菜单项。我有 2 个问题:
我怎样才能正确地摆脱使用 title 属性 of parent 元素,因为我需要阅读 title 属性 of childrens
在菜单元素中使用信号和槽以避免上述错误的正确方法是什么?
请帮助我理解。完整的项目可以在这里拉取:
git clone git://git.code.sf.net/p/breezequick/code breezequick-code
signal
的问题与其声明有关。信号总是被声明为函数:带有签名。换句话说,没有参数的 signal
的形式是
signal <signal_name>()
这也是您收到错误“is not a function
”的原因。除此之外, signals/signal 处理程序的用法是正确的。无论如何,仔细阅读文档不会有什么坏处。 This page 详细介绍了论点。
谈到另一个问题,您做出了错误的假设:在组件 内声明的任何内容都是组件本身 children
的 部分。在这里你声明了一个 BreezeQuickMenu
它有一个 child ListView
。当您使用它并添加 BreezeQuickMenuItem
时,您将它们添加到 ListView
所属的 相同的 集中。最后,children
属性 中有 四个 个元素。此外,通过 model
将 ListView
添加到 自身 中,你会把事情搞得一团糟,以至于呈现完全不相关的字符串。
有几种方法可以将 Items
处理为视图的模型成员,包括 VisualItemModel
and using object Instanced as models。但是,通过浏览您的代码,很明显您想要定义一个以声明方式添加菜单项的组件。在这种情况下使用 children
是不够的。您还需要 default
属性:
An object definition can have a single default property. A default property is the property to which a value is assigned if an object is declared within another object's definition without declaring it as a value for a particular property.
因此您可以为您的 BreezeQuickMenu
定义 default
属性 并利用它为您的列表获得所需的 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) 中我们说“在 BreezeQuickMenu
中声明的所有 Item
都自动 children
addItem
的内部声明 Item
(2)。通过这种方式,ListView
保持分开,而所有 BreezeQuickMenuItem
聚集在一起,在 addItem
下children
属性. 此时,对 ListView
和 model
(3) 使用相同的 children
属性 就足够了就是这样。