Qt5中QML自定義環(huán)形菜單/環(huán)形選擇框的實(shí)現(xiàn)
Qt5 中本身提供了扇形菜單 PieMenu,屬于 QtQuick.Extras 模塊,這個(gè)模塊是拓展自 QtQuick.Control1 的,QtQuick.Control1 在 Qt5 高版本被廢棄,并在 Qt6 移除。

不過我們也可以用 QtQuick.Control2 的組件自定義樣式來實(shí)現(xiàn)環(huán)形或扇形的菜單和選擇框。主要思路就是使用 PathView 來替換默認(rèn)的 ListView,再改下彈框的背景樣式。
ItemDelegate 需要設(shè)置給 ComboBox 或者 Menu,而不是 View。最好用 Button 的相關(guān)類型(默認(rèn)是 ItemDelegate 類型),因?yàn)榻M件默認(rèn)這些小部件是 Button 類型,內(nèi)部 cast 成按鈕來處理的。而且用按鈕就不用自己處理下拉框 currentIndex,內(nèi)部會(huì)自己處理,這也避免了我們在這個(gè) delegate 對 currentIndex 賦值后導(dǎo)致其屬性綁定失效的問題。
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();
}自定義的時(shí)候遇到一點(diǎn)狀況,就是 PathView 替代 ListView 作為 Menu 的 contentItem 后,Menu 的 contentData 和 contentModel 始終會(huì)多一個(gè)表示高亮的 Item,這樣環(huán)形路徑就有個(gè)缺口,目前我只能將顯示的 Item 個(gè)數(shù)減去一個(gè)來使顯示效果正常。
contentItem: PathView {
model: control.contentModel
//把PathView放Menu,會(huì)有一個(gè)高亮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
//環(huán)形選擇框
//龔建波 2022-03-13
//note:彈框?yàn)閜op會(huì)被限制在window內(nèi)
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環(huán)形的角度范圍和延申半徑
property int angle: 1
property int spread: 1
//pop彈出和隱藏時(shí)的過渡動(dòng)畫
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 {
//一個(gè)圓環(huán)路徑
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
//環(huán)形菜單
//龔建波 2022-03-13
//note:彈框?yàn)閜op會(huì)被限制在window內(nèi)
Menu {
id: control
implicitWidth: 250
implicitHeight: 250
margins: 0
padding: 0
//pathview環(huán)形的角度范圍和延申半徑
property int angle: 1
property int spread: 1
//pop彈出和隱藏時(shí)的過渡動(dòng)畫
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,會(huì)有一個(gè)高亮Item被放到contentModel,減去
pathItemCount: control.count > 0 ? control.count - 1 : 0
//currentIndex: control.currentIndex
//highlightRangeMode: PathView.NoHighlightRange
interactive: false
path: Path {
//一個(gè)圓環(huán)路徑
PathAngleArc {
centerX: 125; centerY: 125
radiusX: control.spread; radiusY: control.spread
moveToStart: true
startAngle: 0
sweepAngle: control.angle
}
}
}
background: Item { }
}到此這篇關(guān)于Qt5中QML自定義環(huán)形菜單/環(huán)形選擇框的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Qt5 QML環(huán)形菜單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++使用動(dòng)態(tài)內(nèi)存分配的原因解說
這篇文章主要介紹了C++使用動(dòng)態(tài)內(nèi)存分配的原因解說,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
C語言棧順序結(jié)構(gòu)實(shí)現(xiàn)代碼
一個(gè)能夠自動(dòng)擴(kuò)容的順序結(jié)構(gòu)的棧 ArrStack 實(shí)例 (GCC編譯),有需要的朋友可以參考一下2013-10-10
C語言實(shí)現(xiàn)修改文本文件中特定行的實(shí)現(xiàn)代碼
最近由于項(xiàng)目需要實(shí)現(xiàn)修改文件的功能,所以,博主認(rèn)真查閱了一些資料,但是,很遺憾,并沒有太多的收獲2013-06-06
zlib庫壓縮和解壓字符串STL string的實(shí)例詳解
這篇文章主要介紹了zlib庫壓縮和解壓字符串STL string的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-10-10

