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

相关文章

  • C++使用动态内存分配的原因解说

    C++使用动态内存分配的原因解说

    这篇文章主要介绍了C++使用动态内存分配的原因解说,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • C语言栈顺序结构实现代码

    C语言栈顺序结构实现代码

    一个能够自动扩容的顺序结构的栈 ArrStack 实例 (GCC编译),有需要的朋友可以参考一下
    2013-10-10
  • c语言的程序环境与预处理详解

    c语言的程序环境与预处理详解

    大家好,本篇文章主要讲的是c语言的程序环境与预处理详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • C++输入流和输出流 超级详细

    C++输入流和输出流 超级详细

    C++ 的开发者认为数据输入和输出的过程也是数据传输的过程,数据像水一样从一个地方流动到另一个地方,所以 C++ 中将此过程称为“流”,实现此过程的类称为“流类”。下面小编将详细介绍这个话题,需要的朋友可以参考一下
    2021-09-09
  • C语言实现修改文本文件中特定行的实现代码

    C语言实现修改文本文件中特定行的实现代码

    最近由于项目需要实现修改文件的功能,所以,博主认真查阅了一些资料,但是,很遗憾,并没有太多的收获
    2013-06-06
  • C语言实现控制台扫雷小游戏

    C语言实现控制台扫雷小游戏

    这篇文章主要为大家详细介绍了C语言实现控制台扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • C语言超细致讲解循环语句

    C语言超细致讲解循环语句

    我们说到当满足特定条件时,就会执行if语句或者switch语句后面的语句,否则不执行,但是这只能执行一次,在日常生活中,有些事情是需要重复去做的,C语句就为此引入了循环语句。所以今天继续为大家分享C语言循环家族
    2022-05-05
  • C++函数模板的使用详解

    C++函数模板的使用详解

    大家好,本篇文章主要讲的是C++函数模板的使用详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • zlib库压缩和解压字符串STL string的实例详解

    zlib库压缩和解压字符串STL string的实例详解

    这篇文章主要介绍了zlib库压缩和解压字符串STL string的实例详解的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
    2017-10-10
  • C++中如何将数据保存为CSV文件

    C++中如何将数据保存为CSV文件

    这篇文章主要介绍了C++中如何将数据保存为CSV文件,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11

最新评论