ListView的信号和菜单元素插槽 [英] ListView signals and slots for menu elements
问题描述
我想实现某种自定义菜单的自定义元素。最终的目标是要建立某种形式的文字和图标,弹出菜单。不过,在创建过程中我遇到一些问题。我可以显示2主要问题:
- 有标题为一个陌生的菜单元素
世界,你好
在第一位置(看起来像它的阅读应用程序窗口标题):
<醇开始=2>
QRC:/BreezeQuickMenu.qml:45:类型错误:Property对象QQuickListView(0x1120830)的点击不是一个函数
下面是我的实际code:
main.qml
进口QtQuick 2.2
进口QtQuick.Controls 1.1
进口QtQuick.Window 2.2ApplicationWindow {
标题:QSTR(Hello World的)
宽度:Screen.width
高度:Screen.height
可见:真
ID:赢
颜色:brPalette.normalBackground
BreezeQuickMenu {
ID:brMenu
X:490
Y:199
宽度:128
身高:256
调色板:brPalette
menuFont.pointSize:16
BreezeQuickMenuItem {
标题:项目1
onClicked:mbox.show()
}
BreezeQuickMenuItem {
标题:项目2
}
BreezeQuickMenuItem {
标题:第3项
}
}
}
BreezeQuickMenu.qml
进口QtQuick 2.4项{
ID:根
物业BreezeQuickPalette调色板:BreezeQuickPalette
属性别名CURRENTINDEX:menuList.currentIndex
物业字体menuFont
物业布尔menuVisible:假的
implicitWidth:128
implicitHeight:menuList.height
列表显示{
ID:菜单列表
anchors.fill:父
型号:root.children
片段:真
代表:组件{
ID:菜单项
长方形 {
ID:MenuElement的
物业布尔isCurrentItem:ListView.isCurrentItem
锚{
左:parent.left
右:parent.right
}
颜色:palette.normalBackground
高度:menuText.font.pixelSize * 1.2
文字{
ID:menuText
anchors.fill:父
文本:标题
颜色:palette.normalText
字体:menuFont
}
鼠标区域{
anchors.fill:父
hoverEnabled:真
onClicked:{
menuList.currentIndex =指数
menuList.model [指数] .clicked()
}
}
}
}
}
}
BreezeQuickMenuItem.qml
进口QtQuick 2.4项{
ID:根
属性字符串标题:菜单元素
点击信号
}
正如你可以看到我试图实现菜单列表,并用自己的信号菜单项。我有2个问题:
-
我怎样才能正确地摆脱使用父元素的title属性,因为我需要阅读儿童的title属性
-
什么是在菜单元素使用信号和槽,以避免上述错误的正确的做法?
请帮我明白了。整个项目可以在这里拉:
混帐混帐克隆://git.$c$c.sf.net/p/breezequick/$c$c breezequick- code
与信号问题
与它的声明。信号始终声明为一个功能是:用签名。换句话说,一个信号
不带参数的形式
信号u signal_name&GT;()
这也是为什么你得到了错误不是一个函数
。除此之外,信号/信号处理程序的使用是正确的。总之,阅读仔细的文档不会受到伤害。 本页面详细覆盖的说法。
来到另一个问题,你做出了错误的假设:任何的一个组件内声明的是的的儿童的部分组件
本身。在这里,你声明的 BreezeQuickMenu
具有子的ListView
。当你使用它,并添加 BreezeQuickMenuItem
S,将它们添加到的相同的设置该的ListView
所属。最后,你必须的四的在子元素
属性。此外,通过在添加
你陷入困境的事情了指向一个完全无关的字符串被渲染。的ListView
来的本身的模型
有几种方法可以处理项目
作为视图模型成员,inclusing的 visualItemModel
并使用的对象实例化作为模型的。然而,撇您code,很显然,要定义它增加了一个声明的方式菜单项的组成部分。使用孩子
是不是在这种情况下,就足够了。您还需要在默认
属性:
这是对象定义可以有一个单一的默认属性。默认属性为的属性。它如果一个对象是另一个对象的定义中声明的值赋给没有宣布它为值的特定属性。
块引用>因此,你可以定义
默认
属性的BreezeQuickMenu
并利用它来获得所需的孩子
为您的列表。一种常见的方法是以下(code简体):进口QtQuick 2.4项{
ID:根
物业BreezeQuickPalette调色板:BreezeQuickPalette
属性别名CURRENTINDEX:menuList.currentIndex //默认的声明(1)
默认属性别名内容:addItem.children //项到其中内声明同时将属于(2)
项{
ID:的addItem
} 物业字体menuFont
物业布尔menuVisible:假的 implicitWidth:128
implicitHeight:menuList.height
列表显示{
ID:菜单列表
anchors.fill:父
型号://内容的默认属性的使用(3)
片段:真
代表:矩形{
//您当前的委托code
}
}
}的基本思想是还利用属性
别名
:基本上都在(1)我们说,所有的项目
在<$ C $宣布ş C> BreezeQuickMenu 将自动孩子
的addItem $ C $的C
>这是一个内声明的项目
(2),这样的的ListView
保持分开,而所有的BreezeQuickMenuItem
聚集在一起,在的addItem
孩子
属性。在这一点上,它是足够使用相同的孩子
属性作为模式
(3)为的ListView
,这就是吧。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 formsignal <signal_name>()
That'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: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.
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):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 } } }
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.这篇关于ListView的信号和菜单元素插槽的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!