QT开发中文网

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
        //... ...
    }

主要代码:

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 { }
}

原文作者:亿速云
原文地址:https://www.yisu.com/zixun/690698.html

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://qt.0voice.com/?id=1235

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?