如何在QML应用中创建一个Context Menu

我们在很多的系统中看见可以在屏幕的一个地方长按,然后就可以根据当前显示的上下文弹出一个菜单。菜单中可以有一些选项,比如删除,修改该项。这种一般在ListViewGridView中常见。今天,我们就在这个例程中详细介绍如何实现这个功能。

对ListView来说,我们只需要对它的delegate做一些修改:

        Component {
            id: listDelegate

            ListItem {
                id: delegateItem
                width: listView.width; height: units.gu(10)
                onPressAndHold: ListView.view.ViewItems.dragMode =
                                !ListView.view.ViewItems.dragMode

                Image {
                    id: pic
                    height: parent.height - units.gu(1)
                    width: height
                    anchors.verticalCenter: parent.verticalCenter
                    anchors.left: parent.left
                    anchors.leftMargin: units.gu(0.5)
                    source: image
                }

                Column {
                    id: content
                    anchors.top: parent.top
                    anchors.left: pic.right
                    anchors.leftMargin: units.gu(2)
                    anchors.topMargin: units.gu(1)
                    width: parent.width - pic.width - units.gu(1)
                    height: parent.height
                    spacing: units.gu(1)

                    Label {
                        text: name
                    }

                    Label { text: description }

                    Label {
                        text: '$' + Number(cost).toFixed(2)
                        font.bold: true
                    }
                }

                ListView.onAdd: SequentialAnimation {
                    PropertyAction { target: delegateItem; property: "height"; value: 0 }
                    NumberAnimation { target: delegateItem; property: "height"; to: delegateItem.height; duration: 250; easing.type: Easing.InOutQuad }
                }

                ListView.onRemove: SequentialAnimation {
                    PropertyAction { target: delegateItem; property: "ListView.delayRemove"; value: true }
                    NumberAnimation { target: delegateItem; property: "height"; to: 0; duration: 250; easing.type: Easing.InOutQuad }

                    // Make sure delayRemove is set back to false so that the item can be destroyed
                    PropertyAction { target: delegateItem; property: "ListView.delayRemove"; value: false }
                }

                /* create an empty item centered in the image to align the popover to */
                Item {
                    id: emptyItemForCaller
                    anchors.centerIn: parent
                    z: 100

                }

                Component {
                    id: actPopComp

                    ActionSelectionPopover {
                        id: actPop
                        delegate: ListItems.Standard {
                            text: action.text
                        }

                        actions: ActionList {
                            Action {
                                text: "Add 1 dollar"
                                iconName: "add"
                                onTriggered: {
                                    PopupUtils.close(actPop);
                                    console.log("Add 1 dollar");
                                    fruitModel.setProperty(index, "cost", cost + 1.0);
                                }
                            }
                            Action {
                                text: "Deduct 1 dollar"
                                iconName: "remove"
                                onTriggered: {
                                    PopupUtils.close(actPop);
                                    console.log("Deduct 1 dollar");
                                    fruitModel.setProperty(index, "cost", Math.max(0,cost-1.0));
                                }
                            }
                            Action {
                                text: "delete"
                                iconName: "delete"

                                onTriggered: {
                                    console.log("delete the item!");
                                    fruitModel.remove(index)
                                }
                            }
                        }
                    }
                }

                MouseArea {
                    anchors.fill: parent
                    onPressAndHold: {
                        PopupUtils.open(actPopComp, emptyItemForCaller);
                    }

                    onClicked: {
                        console.log("we can do something else!");
                    }
                }
            }
        }

从上面的代码中可以看出:

  /* create an empty item centered in the image to align the popover to */
                Item {
                    id: emptyItemForCaller
                    anchors.centerIn: parent
                    z: 100

                }

我们使用了一个空的Item来作为一个placeholder。这个是为了给我们在长按ListView中项时,来提供一个位置显示我们的Popup menu。

当我们长按我们的ListView中的项时,我们可以通过如下的方法来得到事件并弹出我们所需要的Popup:

               MouseArea {
                    anchors.fill: parent
                    onPressAndHold: {
                        PopupUtils.open(actPopComp, emptyItemForCaller);
                    }

                    onClicked: {
                        console.log("we can do something else!");
                    }
                }

这里,我们的actPopComp的设计为:

                Component {
                    id: actPopComp

                    ActionSelectionPopover {
                        id: actPop
                        delegate: ListItems.Standard {
                            text: action.text
                        }

                        actions: ActionList {
                            Action {
                                text: "Add 1 dollar"
                                iconName: "add"
                                onTriggered: {
                                    PopupUtils.close(actPop);
                                    console.log("Add 1 dollar");
                                    fruitModel.setProperty(index, "cost", cost + 1.0);
                                }
                            }
                            Action {
                                text: "Deduct 1 dollar"
                                iconName: "remove"
                                onTriggered: {
                                    PopupUtils.close(actPop);
                                    console.log("Deduct 1 dollar");
                                    fruitModel.setProperty(index, "cost", Math.max(0,cost-1.0));
                                }
                            }
                            Action {
                                text: "delete"
                                iconName: "delete"

                                onTriggered: {
                                    console.log("delete the item!");
                                    fruitModel.remove(index)
                                }
                            }
                        }
                    }
                }

在这里,我们有三个Action的菜单。

运行我们的应用:

  

整个项目的源码在: git clone https://gitcafe.com/ubuntu/contextmenu.git

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-07 00:32:12

如何在QML应用中创建一个Context Menu的相关文章

如何在QML应用中实现一个Splash画面

在QML应用中,我们经常要用到一个SplashScreen的画面来渲染我们的应用.那么我们怎么在自己的应用中做一个Splash Screen呢? 首先我们来设计一个自己的SplashScreen的QML模块: SplashScreen.qml import QtQuick 2.0 Item { id: splash anchors.fill: parent property int timeoutInterval: 2000 signal timeout Image { id: splashIm

如何在QML应用中得到一个Item的所有属性,信号及方法

Item是QML语言中最基本的元素.有时为了方便,我们可以列出它里面的所有的属性,信号及方法.我们可以通过这个方法来修改我们的属性等.在QML语言中,所有的可视的控件都是继承于Item的. 下面我们来通过一个例子来展示如何这么做.我们可以设计一个简单的QML应用如下: import QtQuick 2.0 import Ubuntu.Components 1.1 /*! \brief MainView with a Label and Button elements. */ MainView {

如何在QML应用中启动Scope

在这篇文章中,我们将介绍如何在QML应用中调用Scope,并把搜索的关键词传进去.这对有些QML应用需要用到Scope的情况非常有用.更多关于url-dispatcher的知识,请在文章"使用URL dispatcher的范例"看到. Scope ID 首先我们来讲一下什么是Scope ID.我们打开我们创建的任何一个Scope的manifest.json文件: { "architecture": "@[email protected]", &q

如何在oracle 12c中创建普通用户

-------如何在oracle 12c中创建普通用户------- [[email protected] ~]$ sqlplus / as sysdba SQL*Plus: Release 12.1.0.2.0 Production on Sun Nov 29 21:43:50 2015 Copyright (c) 1982, 2014, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edit

如何在RCP程序中添加一个banner栏

前言:这段时间还算比较空闲,我准备把过去做过的有些形形色色,甚至有些奇怪的研究总结一下,也许刚好有人用的着也不一定,不枉为之抓耳挠腮的时光和浪费的电力.以前有个客户提出要在RCP程序中添加一个banner栏,研究了很久才搞定.代码是基于eclipse4.3.2的. 先看一下效果预览: 为了添加一个banner栏,我们必须重写RCP程序最外层的layout类,即TrimmedPartLayout.java.这个layout类是用来控制menu,toolbar等最基本的layout布局的.我们写一个

在sql server中创建一个只读login

在SQL Server中创建一个Login,并为这个login授予只读的权限 --create Login Name create login [domain\login] from windows; --create --UserName Create User DWReadOnly for login [domain\login] --Grant readonly ALTER ROLE [db_datareader] add MEMBER DWReadOnly Appendix 服务器角色参

在windows中创建一个影子用户

在windows中创建一个影子用户(看不到图请下载附件) 我们可以在windows操作系统中建立一个影子用户,也就是它是实际存在的,但是不会在登录时或者用户组中显示,我们可以赋予影子用户管理员权限,可以在某些情况下管理员不可用时使用. 建立影子用户之前,我们先介绍几个概念: SAM数据库:对用户登录用户名和密码进行验证. 注册表:相当于windows的神经系统,很重要. 策略管理器:它实际是注册表的管理工具,因为直接修改注册表是困难和危险的. 下面我们创建影子用户: 1)影子用户名称必须以$结尾

如何在 javascript / js 中 建立一个map

建立map的方式(其实用的是json实现方式) var a = {}; a["key1"] = "value1"; a["key2"] = "value2"; 既然是个map就有检索某个键是否存在的方法,这样写 if ("key1" in a) { // something } else { // something else } 简单的一句话声明map里面的key和value的方式: var a = {'

【实战】在BingoCloudOS中创建一个blog环境

本文通过实战方式了解下在品高云(BingoCloudOS)中如何快速部署一个wordpress的blog站点(包括web和数据库) 涉及服务:弹性服务器(EC2) 涉及版本:所有版本 涉及功能点:镜像.密钥.远程连接.安全组.存储卷.wordpress下载与安装 1.创建实例前的准备 1.1.准备镜像 系统镜像由云平台管理员在进行云平台初始化时准备,普通用户直接使用即可,用户对于需要的镜像可在[基础服务→计算→镜像]的搜索内容框中对镜像进行搜索,若云平台中暂无您需要的镜像时可向管理员申请,或基于