ListView信号和菜单元素的插槽 [英] ListView signals and slots for menu elements

查看:169
本文介绍了ListView信号和菜单元素的插槽的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用自定义元素实现某种自定义菜单。最终的目标是创建一些包含文本和图标的弹出式菜单。但在创作过程中,我遇到了一些问题。我可以显示2个主要问题:

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:


  1. 有一个奇怪的菜单元素,标题为 Hello world 在第一个位置(看起来像是应用程序窗口的标题):

  1. There is a strange menu element with title Hello world at the first position (looks like it's read title of application window):


  1. 我收到错误,如 qrc:/BreezeQuickMenu.qml:45:TypeError:属性点击的对象QQuickListView(0x1120830)不是一个函数

  1. From time to time I'm getting errors like qrc:/BreezeQuickMenu.qml:45: TypeError: Property 'clicked' of object QQuickListView(0x1120830) is not a function

这是我的实际代码:

main.qml p>

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:


  • 如何正确摆脱使用父元素的title属性,因为我需要阅读标题

  • 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, a signal without parameters has the form

signal <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.

出于其他问题,您做出了错误的假设:在组件中声明的内容是 c $ c>组件本身。在这里,你宣布了一个 BreezeQuickMenu ,它有一个孩子 ListView 。当您使用它并添加 BreezeQuickMenuItem 时,您将它们添加到 ListView 属于。最后,您在 children 属性中有四个元素。此外,通过模型 ListView 添加到本身,您会将事情指出一个完全不相关的字符串被渲染。

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 a BreezeQuickMenu which has a child ListView. When you use it and add the BreezeQuickMenuItems, you add them to the same set to which the ListView belongs. In the end you have four elements in the children property. Also, by adding the ListView to itself through the model you mess up things to the point that a totally unrelated string is rendered.

有几种方法来处理项目作为视图的模型成员,包含 VisualItemModel 并使用对象实例化作为模型。但是,通过剔除您的代码,很明显,您想定义一个以声明方式添加菜单项的组件。在这种情况下,使用 children 是不够的。您还需要默认值属性:

There are several ways to handle Items as model members for a view, inclusing VisualItemModel 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. Using children is not sufficient in this case. You also need the default 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.

因此,您可以为 BreezeQuickMenu 定义默认属性,并利用它为您的列表获取所需的儿童。一个常见的方法将是以下(代码简化):

Hence you can define the default property for your BreezeQuickMenu and exploit it to obtain the desired children 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
        }
    }
}

基本ID ea还要利用财产别名 :基本上在(1)我们说在$ code> BreezeQuickMenu中声明的所有项目 code>自动儿童 addItem 这是一个内部声明的项目(2)。以这种方式, ListView 保持分开,而所有 BreezeQuickMenuItem 都集合在 addItem下 children 属性。在这一点上,使用相同的 children 属性作为模型(3) ListView 就是这样。

The basic idea is to exploit also property alias: basically in (1) we are saying that "all the Items declared inside BreezeQuickMenu are automatically children of addItem which is an inner declared Item (2). In this way the ListView is kept apart whereas all the BreezeQuickMenuItem are gathered together, under addItem children property. At this point, it is sufficient to use the same children property as the model (3) for the ListView and that's it.

这篇关于ListView信号和菜单元素的插槽的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆