qml自定义控件----自定义菜单

  • 效果

qml自定义控件----自定义菜单_第1张图片

  • 摘要

 这段时间在写树的时候需要用到右键菜单,但是原生的不太好看,且用起来有点僵硬(不太熟悉),于是抱着手艺人的素养,就自己鼓捣了一个出来,虽然不一定非常通用,但是自己做出来的使用比较方便,后期的改动也会比较方便。

  • 原理

为了更方便的调用下级节点,第一级菜单使用的是Repeater,第二级使用的是listview,通过它们自身的动态创建,来实现多级菜单,而为了更方便的使用,菜单的model使用Jason来传入,所以基本思路就是解析传入的model,根据model来动态创建节点,以实现菜单的效果。

  • 代码

main.qml  子定义菜单的调用 

import QtQuick 2.7
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("闻天语~")
    property var model: {"七里香":["借口","外婆","将军","搁浅","乱舞春秋","困兽之斗","园游会"],
                         "十一月的萧邦":["夜曲","发如雪","推流","枫"],
                         "依然范特西":["夜的第七章","听妈妈的话","本草纲目"],
                         "我很忙我很忙":["牛仔很忙","彩虹","蒲公英的约定"],
                         "魔杰座":["稻香","蛇舞","花海","魔术先生","说好的幸福呢","兰亭序","乔克叔叔"],
                         "叶惠美":["晴天"," 东风破","她的睫毛"],
                         "八度空间":["半岛铁盒","龙拳","回到过去"],
    }
    color: "dimgray"
    MouseArea{
        anchors.fill: parent
        acceptedButtons: Qt.RightButton|Qt.LeftButton
        onClicked: {
            if(mouse.button == Qt.RightButton)
            {
                menu.show(mouse.x,mouse.y)
            }else{
                menu.close()
            }
        }
    }
    MenuEx{
        id:menu
        visible: false
        mainModel:model
        btnHeight: 25
        width: 100
        x:20
        y:20
    }
}

MenuItemEx.qml 菜单的子项

import QtQuick 2.0
import QtQuick.Controls 1.4

Rectangle{
    id:itemRoot
    property variant model: []
    property string showText : ""
    property ExclusiveGroup exclusiveGroup:exp
    property bool checked: false
    onExclusiveGroupChanged: {
        if (exclusiveGroup)
            exclusiveGroup.bindCheckable(itemRoot)
    }
    height:btnHeight
    color:checked?colo_c:menuRoot.color
    Text {
        text: showText
        anchors.centerIn: parent
    }
    MouseArea{
        id:mainMouse
        anchors.fill: parent
        hoverEnabled:true
        onEntered:checked=true
    }
    Component.onCompleted:
    {
        for(var i in model)
        {
            listModel.append({"sText": model[i]})
            console.log("s"+i ,model[i])
        }
    }
    ListModel
    {
        id:listModel
    }
    Rectangle
    {
        anchors.left:parent.right
        anchors.leftMargin: 3
        height: parent.height*model.length+2*extra
        width: parent.width
        color: menuRoot.color
         visible:itemRoot.checked
         radius: extra
        ListView
        {
            model:listModel
            height: parent.height-8
            width: parent.width
            y:extra
            id:listview
            delegate:Rectangle
            {
                color: listview.currentIndex==index?"lightblue": childMouse.containsMouse?colo_c:menuRoot.color
                Text {
                   x:20
                    anchors.verticalCenter: parent.verticalCenter
                    text: sText
                }
                height:btnHeight
                width:itemRoot.width
                MouseArea{
                    anchors.fill: parent
                    id:childMouse
                    hoverEnabled: true
                    onClicked: {
                            listview.currentIndex=index
                    }
                }
            }
        }
    }
}

MenuEx.qml 菜单

import QtQuick 2.0
import QtQuick.Controls 1.4

Rectangle{
    id:menuRoot
    color: "white"
    property int btnHeight: value
    property int extra: 5
    property variant mainModel:[]
    property variant keys : []
    property string colo_c: "lightgray"
    height: btnHeight*keys.length+2*extra
    radius: extra
    Component.onCompleted:
    {
        keys=Object.keys(mainModel)
        for (var i in keys)
        {
            mainListModel.append({"btnText":keys[i]})
        }
    }
    ExclusiveGroup{id:exp}
    ListModel
    {
        id:mainListModel
    }
    ListView
    {
        y:extra
        height: parent.height-8
        model:mainListModel
        width: parent.width
        delegate: MenuItemEx
        {
        showText:btnText
        model:mainModel[btnText]
        width:menuRoot.width
    }
}
function show(inX,inY)
{
    menu.x=inX
    menu.y=inY
    visible=true
}
function close()
{
    exp.current.checked=false
     visible=false
}
}
  • 扩展

因为只是个母本,所以真的需要什么功能可以自己去扩展,手艺人更多的是提供一个思路。因为目前是只支持两级菜单,所以以后可以拓展出多级来,和现在的思路一样,通过解析传入的Jason是否存在多级菜单,来确认是否需要再复用MenuItemEx。如果想要排序也很简单,解析出来的model在加入之前,先把解出来的列表排个序,比如第一级菜单,就可以在传入Repeater之前调用keys.sort()。暂时能想到的扩展就这些了,如果有什么好的建议或者疑问,请联系QQ995187021.

你可能感兴趣的:(QML)