当前位置:   article > 正文

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 赋值后导致其属性绑定失效的问题。

  1. QQuickAction *QQuickMenu::actionAt(int index) const
  2. {
  3. Q_D(const QQuickMenu);
  4. QQuickAbstractButton *item = qobject_cast<QQuickAbstractButton *>(d->itemAt(index));
  5. if (!item)
  6. return nullptr;
  7. return item->action();
  8. }

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

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

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

 

 主要代码:

  1. import QtQuick 2.12
  2. import QtQuick.Window 2.12
  3. import QtQuick.Controls 2.12
  4. Window {
  5. width: 640
  6. height: 480
  7. visible: true
  8. title: qsTr("PathView")
  9. Row {
  10. anchors.centerIn: parent
  11. spacing: 20
  12. MyComboBox {
  13. model: 10
  14. }
  15. Button {
  16. width: 60
  17. height: 30
  18. text: "menu"
  19. background: Rectangle {
  20. radius: 15
  21. color: "red"
  22. border.color: "black"
  23. }
  24. onClicked: {
  25. menu.popup()
  26. }
  27. MyMenu {
  28. id: menu
  29. anchors.centerIn: parent
  30. Action { text: "1" }
  31. Action { text: "2" }
  32. Action { text: "3" }
  33. Action { text: "4" }
  34. Action { text: "5" }
  35. Action { text: "6" }
  36. Action { text: "7" }
  37. Action { text: "8" }
  38. Action { text: "9" }
  39. Action { text: "10" }
  40. }
  41. }
  42. }
  43. }
  1. import QtQuick 2.12
  2. import QtQuick.Controls 2.12
  3. //环形选择框
  4. //龚建波 2022-03-13
  5. //note:弹框为pop会被限制在window内
  6. ComboBox {
  7. id: control
  8. implicitWidth: 30
  9. implicitHeight: 30
  10. opacity: 0.9999
  11. delegate: ItemDelegate {
  12. width: 30
  13. height: width
  14. padding: 0
  15. background: Rectangle {
  16. radius: width / 2
  17. color: "green"
  18. border.color: "black"
  19. }
  20. contentItem: Text {
  21. text: modelData
  22. padding: 0
  23. verticalAlignment: Text.AlignVCenter
  24. horizontalAlignment: Text.AlignHCenter
  25. }
  26. }
  27. contentItem: Text {
  28. text: control.displayText
  29. padding: 0
  30. verticalAlignment: Text.AlignVCenter
  31. horizontalAlignment: Text.AlignHCenter
  32. }
  33. indicator: null
  34. background: Rectangle {
  35. radius: 15
  36. color: "green"
  37. border.color: "black"
  38. }
  39. popup: Popup {
  40. id: pop
  41. width: 200
  42. height: width
  43. anchors.centerIn: parent
  44. margins: 0
  45. padding: 0
  46. //pathview环形的角度范围和延申半径
  47. property int angle: 1
  48. property int spread: 1
  49. //pop弹出和隐藏时的过渡动画
  50. enter: Transition {
  51. ParallelAnimation {
  52. NumberAnimation { property: "angle"; from: 1; to: 360; duration: 500 }
  53. NumberAnimation { property: "spread"; from: 1; to: 100; duration: 500 }
  54. }
  55. }
  56. exit: Transition {
  57. ParallelAnimation {
  58. NumberAnimation { property: "angle"; from: 360; to: 1; duration: 500 }
  59. NumberAnimation { property: "spread"; from: 100; to: 1; duration: 500 }
  60. }
  61. }
  62. background: Item { }
  63. contentItem: PathView {
  64. model: control.popup.visible ? control.delegateModel : null
  65. //currentIndex: control.highlightedIndex
  66. //highlightRangeMode: PathView.NoHighlightRange
  67. interactive: false
  68. path: Path {
  69. //一个圆环路径
  70. PathAngleArc {
  71. centerX: 100; centerY: 100
  72. radiusX: pop.spread; radiusY: pop.spread
  73. moveToStart: true
  74. startAngle: 0
  75. sweepAngle: pop.angle
  76. }
  77. }
  78. }
  79. }
  80. }
  1. import QtQuick 2.12
  2. import QtQuick.Controls 2.12
  3. //环形菜单
  4. //龚建波 2022-03-13
  5. //note:弹框为pop会被限制在window内
  6. Menu {
  7. id: control
  8. implicitWidth: 250
  9. implicitHeight: 250
  10. margins: 0
  11. padding: 0
  12. //pathview环形的角度范围和延申半径
  13. property int angle: 1
  14. property int spread: 1
  15. //pop弹出和隐藏时的过渡动画
  16. enter: Transition {
  17. ParallelAnimation {
  18. NumberAnimation { property: "angle"; from: 1; to: 360; duration: 500 }
  19. NumberAnimation { property: "spread"; from: 1; to: 100; duration: 500 }
  20. }
  21. }
  22. exit: Transition {
  23. ParallelAnimation {
  24. NumberAnimation { property: "angle"; from: 360; to: 1; duration: 500 }
  25. NumberAnimation { property: "spread"; from: 100; to: 1; duration: 500 }
  26. }
  27. }
  28. delegate: MenuItem {
  29. id: item
  30. width: 30
  31. height: width
  32. padding: 0
  33. spacing: 0
  34. indicator: null
  35. arrow: null
  36. background: Rectangle {
  37. radius: width / 2
  38. color: "red"
  39. border.color: "black"
  40. }
  41. contentItem: Text {
  42. text: item.text
  43. padding: 0
  44. verticalAlignment: Text.AlignVCenter
  45. horizontalAlignment: Text.AlignHCenter
  46. }
  47. }
  48. contentItem: PathView {
  49. implicitWidth: 250
  50. implicitHeight: 250
  51. model: control.contentModel
  52. //把PathView放Menu,会有一个高亮Item被放到contentModel,减去
  53. pathItemCount: control.count > 0 ? control.count - 1 : 0
  54. //currentIndex: control.currentIndex
  55. //highlightRangeMode: PathView.NoHighlightRange
  56. interactive: false
  57. path: Path {
  58. //一个圆环路径
  59. PathAngleArc {
  60. centerX: 125; centerY: 125
  61. radiusX: control.spread; radiusY: control.spread
  62. moveToStart: true
  63. startAngle: 0
  64. sweepAngle: control.angle
  65. }
  66. }
  67. }
  68. background: Item { }
  69. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/418271
推荐阅读
相关标签
  

闽ICP备14008679号