Qt5中QML自定义环形菜单/环形选择框的实现

 更新时间:2022年03月14日 15:58:32   作者:龚建波  
本文主要介绍了Qt5中QML自定义环形菜单/环形选择框的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

Qt5 中本身提供了扇形菜单 PieMenu,属于 QtQuick.Extras 模块,这个模块是拓展自 QtQuick.Control1 的,QtQuick.Control1 在 Qt5 高版本被废弃,并在 Qt6 移除。

不过我们也可以用 QtQuick.Control2 的组件自定义样式来实现环形或扇形的菜单和选择框。主要思路就是使用 PathView 来替换默认的 ListView,再改下弹框的背景样式。

ItemDelegate 需要设置给 ComboBox 或者 Menu,而不是 View。最好用 Button 的相关类型(默认是 ItemDelegate 类型),因为组件默认这些小部件是 Button 类型,内部 cast 成按钮来处理的。而且用按钮就不用自己处理下拉框 currentIndex,内部会自己处理,这也避免了我们在这个 delegate 对 currentIndex 赋值后导致其属性绑定失效的问题。

QQuickAction *QQuickMenu::actionAt(int index) const
{
    Q_D(const QQuickMenu);
    QQuickAbstractButton *item = qobject_cast<QQuickAbstractButton *>(d->itemAt(index));
    if (!item)
        return nullptr;
 
    return item->action();
}

自定义的时候遇到一点状况,就是 PathView 替代 ListView 作为 Menu 的 contentItem 后,Menu 的 contentData 和 contentModel 始终会多一个表示高亮的 Item,这样环形路径就有个缺口,目前我只能将显示的 Item 个数减去一个来使显示效果正常。

    contentItem: PathView {
        model: control.contentModel
        //把PathView放Menu,会有一个高亮Item被放到contentModel,减去
        pathItemCount: control.count > 0 ? control.count - 1 : 0
        //... ...
    }

Demo 链接:https://github.com/gongjianbo/MyTestCode2021/tree/master/Qml/TestQml_20220313_PathView

 

 主要代码:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
 
Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("PathView")
 
    Row {
        anchors.centerIn: parent
        spacing: 20
 
        MyComboBox {
            model: 10
        }
 
        Button {
            width: 60
            height: 30
            text: "menu"
            background: Rectangle {
                radius: 15
                color: "red"
                border.color: "black"
            }
            onClicked: {
                menu.popup()
            }
 
            MyMenu {
                id: menu
                anchors.centerIn: parent
                Action { text: "1" }
                Action { text: "2" }
                Action { text: "3" }
                Action { text: "4" }
                Action { text: "5" }
                Action { text: "6" }
                Action { text: "7" }
                Action { text: "8" }
                Action { text: "9" }
                Action { text: "10" }
            }
        }
    }
}
import QtQuick 2.12
import QtQuick.Controls 2.12
 
//环形选择框
//龚建波 2022-03-13
//note:弹框为pop会被限制在window内
ComboBox {
    id: control
 
    implicitWidth: 30
    implicitHeight: 30
    opacity: 0.9999
 
    delegate: ItemDelegate {
        width: 30
        height: width
        padding: 0
        background: Rectangle {
            radius: width / 2
            color: "green"
            border.color: "black"
        }
        contentItem: Text {
            text: modelData
            padding: 0
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
        }
    }
    contentItem: Text {
        text: control.displayText
        padding: 0
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignHCenter
    }
    indicator: null
    background: Rectangle {
        radius: 15
        color: "green"
        border.color: "black"
    }
    popup: Popup {
        id: pop
        width: 200
        height: width
        anchors.centerIn: parent
        margins: 0
        padding: 0
        //pathview环形的角度范围和延申半径
        property int angle: 1
        property int spread: 1
        //pop弹出和隐藏时的过渡动画
        enter: Transition {
            ParallelAnimation {
                NumberAnimation { property: "angle"; from: 1; to: 360; duration: 500 }
                NumberAnimation { property: "spread"; from: 1; to: 100; duration: 500 }
            }
        }
        exit: Transition {
            ParallelAnimation {
                NumberAnimation { property: "angle"; from: 360; to: 1; duration: 500 }
                NumberAnimation { property: "spread"; from: 100; to: 1; duration: 500 }
            }
        }
        background: Item { }
        contentItem: PathView {
            model: control.popup.visible ? control.delegateModel : null
            //currentIndex: control.highlightedIndex
            //highlightRangeMode: PathView.NoHighlightRange
            interactive: false
            path: Path {
                //一个圆环路径
                PathAngleArc {
                    centerX: 100; centerY: 100
                    radiusX: pop.spread; radiusY: pop.spread
                    moveToStart: true
                    startAngle: 0
                    sweepAngle: pop.angle
                }
            }
        }
    }
}
import QtQuick 2.12
import QtQuick.Controls 2.12
 
//环形菜单
//龚建波 2022-03-13
//note:弹框为pop会被限制在window内
Menu {
    id: control
 
    implicitWidth: 250
    implicitHeight: 250
    margins: 0
    padding: 0
 
    //pathview环形的角度范围和延申半径
    property int angle: 1
    property int spread: 1
    //pop弹出和隐藏时的过渡动画
    enter: Transition {
        ParallelAnimation {
            NumberAnimation { property: "angle"; from: 1; to: 360; duration: 500 }
            NumberAnimation { property: "spread"; from: 1; to: 100; duration: 500 }
        }
    }
    exit: Transition {
        ParallelAnimation {
            NumberAnimation { property: "angle"; from: 360; to: 1; duration: 500 }
            NumberAnimation { property: "spread"; from: 100; to: 1; duration: 500 }
        }
    }
    delegate: MenuItem {
        id: item
        width: 30
        height: width
        padding: 0
        spacing: 0
        indicator: null
        arrow: null
        background: Rectangle {
            radius: width / 2
            color: "red"
            border.color: "black"
        }
        contentItem: Text {
            text: item.text
            padding: 0
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
        }
    }
    contentItem: PathView {
        implicitWidth: 250
        implicitHeight: 250
        model: control.contentModel
        //把PathView放Menu,会有一个高亮Item被放到contentModel,减去
        pathItemCount: control.count > 0 ? control.count - 1 : 0
        //currentIndex: control.currentIndex
        //highlightRangeMode: PathView.NoHighlightRange
        interactive: false
        path: Path {
            //一个圆环路径
            PathAngleArc {
                centerX: 125; centerY: 125
                radiusX: control.spread; radiusY: control.spread
                moveToStart: true
                startAngle: 0
                sweepAngle: control.angle
            }
        }
    }
    background: Item { }
}

到此这篇关于Qt5中QML自定义环形菜单/环形选择框的实现的文章就介绍到这了,更多相关Qt5 QML环形菜单内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • VSCode远程开发调试服务器c/c++代码

    VSCode远程开发调试服务器c/c++代码

    语音相关的好多项目要在linux上跑,但代码开发大多是在PC机上,本篇简单介绍一下怎么在个人电脑上用VSCode远程开发调试服务器上的c/c++代码。感兴趣的朋友跟随小编一起看看吧
    2020-04-04
  • C语言源码实现停车场管理系统

    C语言源码实现停车场管理系统

    这篇文章主要为大家详细介绍了C语言源码实现停车场管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • C语言中关于scanf读取缓存区的问题

    C语言中关于scanf读取缓存区的问题

    scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息,接下来通过本文给大家介绍C语言中关于scanf读取缓存区的问题,需要的朋友一起看看吧
    2021-09-09
  • C语言深入讲解语句与选择结构的使用

    C语言深入讲解语句与选择结构的使用

    这篇文章主要为大家介绍了C语言的语句与选择结构,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • C语言静态版通讯录的设计与实现

    C语言静态版通讯录的设计与实现

    静态版通讯录是一种简单的通讯录实现方式,通过定义固定的数组大小来存储联系人信息。该方法不支持动态增删联系人,但具有实现简单、易于理解的优点。在程序设计中,需注意数组边界溢出等问题
    2023-04-04
  • C++ 学习笔记实战写一个简单的线程池示例

    C++ 学习笔记实战写一个简单的线程池示例

    这篇文章主要为大家介绍了C++实现一个简单的线程池学习实战,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • C语言实现单链表的基本操作分享

    C语言实现单链表的基本操作分享

    单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。本文将为大家介绍C语言中单链表的基本操作,需要的可以参考一下
    2022-10-10
  • QT连接Mysql数据库的实现步骤

    QT连接Mysql数据库的实现步骤

    本文主要介绍了QT连接Mysql数据库的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • C++三体星战小游戏源代码

    C++三体星战小游戏源代码

    这篇文章主要给大家介绍了关于C++三体星战小游戏的相关资料,文中给出了详细完整的代码示例,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • vs2019安装及简单处理技巧(超详细)

    vs2019安装及简单处理技巧(超详细)

    这篇文章主要介绍了vs2019安装及简单处理方法,本文是一篇非常详细的教程,通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06

最新评论