【QML】菜单

标签: QT  qml

相关类型:MenuBar、Menu、MenuItem、MenuSeparator、Action

注意:本文基于Qt Quick Control 2,在帮助文档里搜索MenuBar,将弹出以下选项
在这里插入图片描述
前两个是旧的MenuBar,用法跟最新的不一样,import的时候注意import QtQuick.Controls 2.x,否则会提示错误
同样的事情发生在搜索Menu、MenuItem、MenuSeparator时,也是弹出多个版本,这也是qml很让人头疼的地方,同样名字的类型,往往存在多个不同时期、互不兼容的版本,互相之间其实是两个完全不一样的类型了!


MenuBar
从Qt5.10开始加入,继承自Container,由多个Menu构成

帮助文档里给出了一个简单的例子

在这里插入图片描述

  ApplicationWindow {
      id: window
      width: 320
      height: 260
      visible: true

      menuBar: MenuBar {
          Menu {
              title: qsTr("&File")
              Action { text: qsTr("&New...") }
              Action { text: qsTr("&Open...") }
              Action { text: qsTr("&Save") }
              Action { text: qsTr("Save &As...") }
              MenuSeparator { }
              Action { text: qsTr("&Quit") }
          }
          Menu {
              title: qsTr("&Edit")
              Action { text: qsTr("Cu&t") }
              Action { text: qsTr("&Copy") }
              Action { text: qsTr("&Paste") }
          }
          Menu {
              title: qsTr("&Help")
              Action { text: qsTr("&About") }
          }
      }
  }

Menu
从Qt5.7开始加入,继承自Popup,Popup是qml专门为弹出式控件定义的基类,Menu属于Popup的一种,类似的还有Dialog,Drawer, ToolTip

Menu有两种使用场景:
Context menus; for example, a menu that is shown after right clicking
Popup menus; for example, a menu that is shown after clicking a button
不管哪种,都是通过click事件弹出菜单,它们的区别是第一种是通过 Menu.popup()打开菜单,而第二种是通过Popup.open()打开菜单

一个鼠标右键菜单的例子:
在这里插入图片描述

  MouseArea {
      anchors.fill: parent
      acceptedButtons: Qt.LeftButton | Qt.RightButton
      onClicked: {
          if (mouse.button === Qt.RightButton)
              contextMenu.popup()
      }
      onPressAndHold: {
          if (mouse.source === Qt.MouseEventNotSynthesized)
              contextMenu.popup()
      }

      Menu {
          id: contextMenu
          MenuItem { text: "Cut" }
          MenuItem { text: "Copy" }
          MenuItem { text: "Paste" }
      }
  }

上面通过MenuItem定义菜单子项,也可以通过Action来定义,效果是一样的

  MouseArea {
      anchors.fill: parent
      acceptedButtons: Qt.LeftButton | Qt.RightButton
      onClicked: {
          if (mouse.button === Qt.RightButton)
              contextMenu.popup()
      }
      onPressAndHold: {
          if (mouse.source === Qt.MouseEventNotSynthesized)
              contextMenu.popup()
      }

        Menu {
            id: contextMenu
            Action { text: "Cut" }
            Action { text: "Copy" }
            Action { text: "Paste" }
        }
  }

MenuItem
从Qt5.7开始加入,继承自AbstractButton,提供了一个triggered信号,通过onTriggered事件处理函数,如

Menu {
     id: contextMenu
     MenuItem {
     	text: "Cut" 
     	onTriggered: console.log("menu-cut")
	 }
 }

QAction
从Qt5.10开始加入,继承自QtObject,专门用于菜单栏或者工具栏,可以check,可以分配快捷键。当作为menu的元素时,也被认为是一个MenuItem。

简单的例子:

  ToolButton {
      id: toolButton
      action: copyAction
  }
  Action {
      id: copyAction
      text: qsTr("&Copy")
      icon.name: "edit-copy"
      shortcut: StandardKey.Copy
      onTriggered: window.activeFocusItem.copy()
  }

自定义菜单

Customizing MenuBar

我们可以定制MenuBar的background和delegate,其中delegate定义为 MenuBarItem

例子:
在这里插入图片描述

import QtQuick 2.12
import QtQuick.Controls 2.12

MenuBar {
    id: menuBar

    Menu {
        title: qsTr("File")
        Action { text: "New" }
        Action { text: "Open" }
        Action { text: "Save" }
    }
    Menu {
        title: qsTr("Edit")
        Action { text: "Undo" }
        Action { text: "Redo" }
        MenuSeparator{}
        Action { text: "Cut" }
        Action { text: "Copy" }
        Action { text: "Phaste" }
    }
    Menu {
        title: qsTr("View")
        Action { text: "Manager" }
        Action { text: "Bookmark" }
        Action { text: "Toolbox" }
        Action { text: "Log" }
    }
    Menu {
        title: qsTr("Help")
        Action { text: "Manual" }
        Action { text: "Update" }
        Action { text: "About" }
    }

    delegate: MenuBarItem {
        id: menuBarItem

        contentItem: Text {
            text: menuBarItem.text
            font: menuBarItem.font
            opacity: enabled ? 1.0 : 0.3
            color: menuBarItem.highlighted ? "#ffffff" : "#21be2b"
            horizontalAlignment: Text.AlignLeft
            verticalAlignment: Text.AlignVCenter
            elide: Text.ElideRight
        }

        background: Rectangle {
            implicitWidth: 40
            implicitHeight: 40
            opacity: enabled ? 1 : 0.3
            color: menuBarItem.highlighted ? "#21be2b" : "transparent"
        }
    }

    background: Rectangle {
        implicitWidth: 40
        implicitHeight: 40
        color: "#ffffff"

        Rectangle {
            color: "#21be2b"
            width: parent.width
            height: 1
            anchors.bottom: parent.bottom
        }
    }
}

上面的例子只影响MenuBar的一级菜单,二级菜单需要进一步定制Menu

Customizing Menu

我们可以定制Menu的background 、MenuItem 、MenuSeparator ,其中,MenuItem是每个选项,又可以定制其 background、content item、indicator、arrow,而MenuSeparator则可以定制其 background、content item

我们在上面的MenuBar例子基础上,修改其中名为“View”的Menu:
在这里插入图片描述

        Menu {
            title: qsTr("View")
            Action { text: "Manager"; checkable: true; checked: true  }
            Action { text: "Bookmark"; checkable: true }
            Menu {
                title: "Toolbox"
                Action { text: "Selector" }
                Action { text: "Pen" }
                Action { text: "Brush" }
                MenuSeparator {
                    contentItem: Rectangle {
                        implicitWidth: 200
                        implicitHeight: 1
                        color: "#21be2b"
                    }
                }
                Action { text: "Zoom In" }
                Action { text: "Zoom Out" }
                Action { text: "Rotate" }
                Action { text: "Flip" }
            }
            Action { text: "Log" }

			//定义菜单每个选项的显示行为
            delegate: MenuItem {
                id: menuItem
                implicitWidth: 200
                implicitHeight: 40

                //MenuItem专属的arrow属性,用于定制展开选项的箭头
                arrow: Canvas {
                    x: parent.width - width
                    implicitWidth: 40
                    implicitHeight: 40
                    visible: menuItem.subMenu
                    onPaint: {
                        var ctx = getContext("2d")
                        ctx.fillStyle = menuItem.highlighted ? "#ffffff" : "#21be2b"
                        ctx.moveTo(15, 15)
                        ctx.lineTo(width - 15, height / 2)
                        ctx.lineTo(15, height - 15)
                        ctx.closePath()
                        ctx.fill()
                    }
                }

				//AbstractButton的属性,用于定制选项前的指示标记
                indicator: Item {
                    implicitWidth: 40
                    implicitHeight: 40
                    Rectangle {
                        width: 26
                        height: 26
                        anchors.centerIn: parent
                        visible: menuItem.checkable
                        border.color: "#21be2b"
                        radius: 3
                        Rectangle {
                            width: 14
                            height: 14
                            anchors.centerIn: parent
                            visible: menuItem.checked
                            color: "#21be2b"
                            radius: 2
                        }
                    }
                }

				//用于定制选项文本
                contentItem: Text {
                    leftPadding: menuItem.indicator.width
                    rightPadding: menuItem.arrow.width
                    text: menuItem.text
                    font: menuItem.font
                    opacity: enabled ? 1.0 : 0.3
                    color: menuItem.highlighted ? "#ffffff" : "#21be2b"
                    horizontalAlignment: Text.AlignLeft
                    verticalAlignment: Text.AlignVCenter
                    elide: Text.ElideRight
                }

				//用于定制选项背景
                background: Rectangle {
                    implicitWidth: 200
                    implicitHeight: 40
                    opacity: enabled ? 1 : 0.3
                    color: menuItem.highlighted ? "#21be2b" : "transparent"
                }
            }

			//定制整个菜单的背景
            background: Rectangle {
                implicitWidth: 200
                implicitHeight: 40
                color: "#ffffff"
                border.color: "#21be2b"
                radius: 2
            }
        }

这里偷懒没有定制“Toolbox”的次级菜单,可以通过把上面的例子封装为一个Menu模块,如MyMenu.qml,在创建菜单时直接使用MyMenu就可以达到定制效果


动态创建菜单

(To be continued)

版权声明:本文为Kelvin_Yan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Kelvin_Yan/article/details/109773183

智能推荐

RIP/DHCP/ACL综合实验

组播: 加入组的组成员才会接受到消息,只需要将流量发送一次到组播地址 减少控制面流量,减少头部复制, RIP1  广播   有类  不支持认证 RIP2  组播   无类  (支持VLAN)、支持认证 所有距离矢量路由协议:具有距离矢量特征的协议,都会在边界自动汇总 控制平面  路由的产生是控制平面的流量 数据平面  ...

【Sublime】使用 Sublime 工具时运行python文件

使用 Sublime 工具时报Decode error - output not utf-8解决办法   在菜单中tools中第四项编译系统 内最后一项增添新的编译系统 自动新建 Python.sublime-build文件,并添加"encoding":"cp936"这一行,保存即可 使用python2 则注释encoding改为utf-8 ctr...

java乐观锁和悲观锁最底层的实现

1. CAS实现的乐观锁 CAS(Compare And Swap 比较并且替换)是乐观锁的一种实现方式,是一种轻量级锁,JUC 中很多工具类的实现就是基于 CAS 的,也可以理解为自旋锁 JUC是指import java.util.concurrent下面的包, 比如:import java.util.concurrent.atomic.AtomicInteger; 最终实现是汇编指令:lock...

Python 中各种imread函数的区别与联系

  原博客:https://blog.csdn.net/renelian1572/article/details/78761278 最近一直在用python做图像处理相关的东西,被各种imread函数搞得很头疼,因此今天决定将这些imread总结一下,以免以后因此犯些愚蠢的错误。如果你正好也对此感到困惑可以看下这篇总结。当然,要了解具体的细节,还是应该 read the fuc...

用栈判断一个字符串是否平衡

注: (1)本文定义:左符号:‘(’、‘[’、‘{’…… 右符号:‘)’、‘]’、‘}’……. (2)所谓的字符串的符号平衡,是指字符串中的左符号与右符号对应且相等,如字符串中的如‘(&r...

猜你喜欢

JAVA环境变量配置

位置 计算机->属性->高级系统设置->环境变量 方式一 用户变量新建path 系统变量新建classpath 方式二 系统变量 新建JAVA_HOME,值为JDK路径 编辑path,前加 方式三 用户变量新建JAVA_HOME 此路径含lib、bin、jre等文件夹。后运行tomcat,eclipse等需此变量,故最好设。 用户变量编辑Path,前加 系统可在任何路径识别jav...

常用的伪类选择器

CSS选择器众多 CSS选择器及权重计算 最常用的莫过于类选择器,其它的相对用的就不会那么多了,当然属性选择器和为类选择器用的也会比较多,这里我们就常用的伪类选择器来讲一讲。 什么是伪类选择器? CSS伪类是用来添加一些选择器的特殊效果。 常用的为类选择器 状态伪类 我们中最常见的为类选择器就是a标签(链接)上的为类选择器。 当我们使用它们的时候,需要遵循一定的顺序问题,否则将可能出现bug 注意...

ButterKnife的使用介绍及原理探究(六)

前面分析了ButterKnife的源码,了解其实现原理,那么就将原理运用于实践吧。 github地址:       点击打开链接 一、自定义注解 这里为了便于理解,只提供BindView注解。 二、添加注解处理器 添加ViewInjectProcessor注解处理器,看代码, 这里分别实现了init、getSupportedAnnotationTypes、g...

1.写一个程序,提示输入两个字符串,然后进行比较,输出较小的字符串。考试复习题库1|要求:只能使用单字符比较操作。

1.写一个程序,提示输入两个字符串,然后进行比较,输出较小的字符串。 要求只能使用单字符比较操作。 参考代码: 实验结果截图:...

小demo:slideDown()实现二级菜单栏下拉效果

效果如下,鼠标经过显示隐藏的二级菜单栏 但是这样的时候会存在一个问题,就是鼠标快速不停移入移出会导致二级菜单栏闪屏现象,一般需要使用stop()来清除事件  ...