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环形菜单内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 麻将游戏算法深入解析及实现代码

    麻将游戏算法深入解析及实现代码

    这篇文章主要介绍了麻将游戏算法深入解析及实现代码的相关资料,需要的朋友可以参考下
    2017-03-03
  • C语言实现三子棋

    C语言实现三子棋

    这篇文章主要为大家详细介绍了C语言实现三子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • c语言实现的带通配符匹配算法

    c语言实现的带通配符匹配算法

    这篇文章主要介绍了c语言实现的带通配符匹配算法,需要的朋友可以参考下
    2015-03-03
  • C++使用宏实现动态库加载

    C++使用宏实现动态库加载

    开发的时候,有些项目不能静态链接动态库,需要程序运行时加载动态库。本文将使用宏来实现动态库的加载,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • 用C语言实现二分查找算法

    用C语言实现二分查找算法

    大家好,本篇文章主要讲的是c语言实现二分查找法,感性的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • 单线程会导致死锁你知道吗

    单线程会导致死锁你知道吗

    这篇文章主要为大家详细介绍了单线程会不会导致死锁,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • Visual C++ 常用数据类型转换方法详解

    Visual C++ 常用数据类型转换方法详解

    本文纯粹是总结一下有关类型转换的贴子,需要的朋友可以参考下
    2017-06-06
  • C++实现LeetCode(115.不同的子序列)

    C++实现LeetCode(115.不同的子序列)

    这篇文章主要介绍了C++实现LeetCode(115.不同的子序列),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++ 使用new与delete需注意的原则

    C++ 使用new与delete需注意的原则

    这篇文章主要介绍了C++ 使用new与delete需注意的原则,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下
    2020-08-08
  • vscode ssh远程连接服务器一直卡在下载 vscode server问题解决

    vscode ssh远程连接服务器一直卡在下载 vscode server问题解决

    在使用vscode使用ssh远程连接服务器时,一直卡在下载"vscode 服务器"阶段,本文主要介绍了vscode ssh远程连接服务器一直卡在下载 vscode server问题解决,感兴趣的可以了解一下
    2025-01-01

最新评论