├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── RadialBarDemo.pro ├── RadialBarShape.qml ├── main.cpp ├── main.qml ├── main2.qml ├── qml.qrc ├── radialBarShapeDemo.qml ├── radialbar.cpp └── radialbar.h /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [arunpkio] 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | /.qmake.cache 16 | /.qmake.stash 17 | *.pro.user 18 | *.pro.user.* 19 | *.qbs.user 20 | *.qbs.user.* 21 | *.moc 22 | moc_*.cpp 23 | qrc_*.cpp 24 | ui_*.h 25 | Makefile* 26 | *build-* 27 | 28 | # QtCreator 29 | 30 | *.autosave 31 | 32 | # QtCtreator Qml 33 | *.qmlproject.user 34 | *.qmlproject.user.* 35 | 36 | # QtCtreator CMake 37 | CMakeLists.txt.user 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Arun PK 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RadialBarDemo 2 | Custom radial Progress Bar QML component 3 | This is a Custom Radial Bar created as a component to be used with QML. 4 | 5 | Following are the main properties of this component. 6 | 7 | * startAngle 8 | * spanAngle 9 | * minValue 10 | * maxValue 11 | * value 12 | * dialWidth 13 | * backgroundColor 14 | * foregroundColor 15 | * progressColor 16 | * textColor 17 | * penStyle 18 | * suffixText 19 | * showText 20 | * dialType 21 | * textFont 22 | 23 | The property penStyle can be used to provide two styles which QT is providing which are Qt::FlatCap & Qt::RoundCap. 24 | 25 | The property DialType is peovided as custom enum which will have following properties. 26 | 27 | * FullDial 28 | * MinToMax 29 | * NoDial 30 | 31 | ## Screenshots: 32 | 33 | ![Screen Recording 2021-04-16 at 14 26 52](https://user-images.githubusercontent.com/4667704/115068315-66dd8580-9ef2-11eb-93d9-19b22875216d.gif) 34 | 35 | ![alt tag](https://cloud.githubusercontent.com/assets/4667704/24536488/60bd8b32-15f8-11e7-81a7-997fb6fd119b.png) 36 | 37 | ![alt tag](https://cloud.githubusercontent.com/assets/4667704/24536491/60bf46f2-15f8-11e7-8390-dbc29d35ba7b.png) 38 | 39 | ![alt tag](https://cloud.githubusercontent.com/assets/4667704/24536487/60bcc1ca-15f8-11e7-9a1e-d147eb5d716d.png) 40 | 41 | ![alt tag](https://cloud.githubusercontent.com/assets/4667704/24536490/60bf1bd2-15f8-11e7-892f-e33ad83344ed.png) 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /RadialBarDemo.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | QT += qml quick 4 | CONFIG += c++11 5 | 6 | SOURCES += main.cpp \ 7 | radialbar.cpp 8 | 9 | RESOURCES += qml.qrc 10 | 11 | # Additional import path used to resolve QML modules in Qt Creator's code model 12 | QML_IMPORT_PATH = 13 | 14 | # Additional import path used to resolve QML modules just for Qt Quick Designer 15 | QML_DESIGNER_IMPORT_PATH = 16 | 17 | # The following define makes your compiler emit warnings if you use 18 | # any feature of Qt which as been marked deprecated (the exact warnings 19 | # depend on your compiler). Please consult the documentation of the 20 | # deprecated API in order to know how to port your code away from it. 21 | DEFINES += QT_DEPRECATED_WARNINGS 22 | 23 | # You can also make your code fail to compile if you use deprecated APIs. 24 | # In order to do so, uncomment the following line. 25 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 26 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 27 | 28 | # Default rules for deployment. 29 | qnx: target.path = /tmp/$${TARGET}/bin 30 | else: unix:!android: target.path = /opt/$${TARGET}/bin 31 | !isEmpty(target.path): INSTALLS += target 32 | 33 | HEADERS += \ 34 | radialbar.h 35 | -------------------------------------------------------------------------------- /RadialBarShape.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import QtQuick.Shapes 1.15 3 | 4 | Item { 5 | id: control 6 | 7 | implicitWidth: 200 8 | implicitHeight: 200 9 | 10 | enum DialType { 11 | FullDial, 12 | MinToMax, 13 | NoDial 14 | } 15 | 16 | property real startAngle: 0 17 | property real spanAngle: 360 18 | property real minValue: 0 19 | property real maxValue: 100 20 | property real value: 0 21 | property int dialWidth: 15 22 | 23 | property color backgroundColor: "transparent" 24 | property color dialColor: "#FF505050" 25 | property color progressColor: "#FFA51BAB" 26 | 27 | property int penStyle: Qt.RoundCap 28 | property int dialType: RadialBarShape.DialType.FullDial 29 | 30 | QtObject { 31 | id: internals 32 | 33 | property bool isFullDial: control.dialType === RadialBarShape.DialType.FullDial 34 | property bool isNoDial: control.dialType === RadialBarShape.DialType.NoDial 35 | 36 | property real baseRadius: Math.min(control.width / 2, control.height / 2) 37 | property real radiusOffset: internals.isFullDial ? control.dialWidth / 2 38 | : control.dialWidth / 2 39 | property real actualSpanAngle: internals.isFullDial ? 360 : control.spanAngle 40 | 41 | property color transparentColor: "transparent" 42 | property color dialColor: internals.isNoDial ? internals.transparentColor 43 | : control.dialColor 44 | } 45 | 46 | Shape { 47 | id: shape 48 | anchors.fill: parent 49 | layer.enabled: true 50 | layer.samples: 8 51 | 52 | ShapePath { 53 | id: pathBackground 54 | strokeColor: internals.transparentColor 55 | fillColor: control.backgroundColor 56 | capStyle: control.penStyle 57 | 58 | PathAngleArc { 59 | radiusX: internals.baseRadius - control.dialWidth 60 | radiusY: internals.baseRadius - control.dialWidth 61 | centerX: control.width / 2 62 | centerY: control.height / 2 63 | startAngle: 0 64 | sweepAngle: 360 65 | } 66 | } 67 | 68 | ShapePath { 69 | id: pathDial 70 | strokeColor: control.dialColor 71 | fillColor: internals.transparentColor 72 | strokeWidth: control.dialWidth 73 | capStyle: control.penStyle 74 | 75 | PathAngleArc { 76 | radiusX: internals.baseRadius - internals.radiusOffset 77 | radiusY: internals.baseRadius - internals.radiusOffset 78 | centerX: control.width / 2 79 | centerY: control.height / 2 80 | startAngle: control.startAngle - 90 81 | sweepAngle: internals.actualSpanAngle 82 | } 83 | } 84 | 85 | ShapePath { 86 | id: pathProgress 87 | strokeColor: control.progressColor 88 | fillColor: internals.transparentColor 89 | strokeWidth: control.dialWidth 90 | capStyle: control.penStyle 91 | 92 | PathAngleArc { 93 | radiusX: internals.baseRadius - internals.radiusOffset 94 | radiusY: internals.baseRadius - internals.radiusOffset 95 | centerX: control.width / 2 96 | centerY: control.height / 2 97 | startAngle: control.startAngle - 90 98 | sweepAngle: (internals.actualSpanAngle / control.maxValue * control.value) 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************************* 2 | ** The MIT License (MIT) 3 | ** 4 | ** RadialBar is a free Qt and QML based component. 5 | ** Copyright (c) 2017 Arun PK 6 | ** Email: mailztopk@gmail.com 7 | ** 8 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 9 | ** of this software and associated documentation files (the "Software"), to deal 10 | ** in the Software without restriction, including without limitation the rights 11 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | ** copies of the Software, and to permit persons to whom the Software is 13 | ** furnished to do so, subject to the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be included in 16 | *all 17 | ** copies or substantial portions of the Software. 18 | ** 19 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | ** SOFTWARE. 26 | ************************************************************************************/ 27 | 28 | #include 29 | #include 30 | 31 | #include "radialbar.h" 32 | 33 | int main(int argc, char *argv[]) { 34 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 35 | QGuiApplication app(argc, argv); 36 | 37 | qmlRegisterType("CustomControls", 1, 0, "RadialBar"); 38 | 39 | QQmlApplicationEngine engine; 40 | engine.load(QUrl(QStringLiteral("qrc:/radialBarShapeDemo.qml"))); 41 | 42 | return app.exec(); 43 | } 44 | -------------------------------------------------------------------------------- /main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Window 2.2 3 | import CustomControls 1.0 4 | import QtQuick.Controls 2.0 5 | import QtQuick.Controls 1.2 6 | import QtQuick.Layouts 1.1 7 | 8 | Window { 9 | visible: true 10 | width: 1200 11 | height: 1100 12 | title: qsTr("Hello World") 13 | 14 | Rectangle { 15 | anchors.fill: parent 16 | color: "#1d1d35" 17 | } 18 | 19 | ColumnLayout { 20 | anchors.centerIn: parent 21 | spacing: 50 22 | RowLayout { 23 | id: layout 24 | spacing: 30 25 | RadialBar { 26 | width: 300 27 | height: 300 28 | penStyle: Qt.RoundCap 29 | dialType: RadialBar.FullDial 30 | progressColor: "#1dc58f" 31 | foregroundColor: "#191a2f" 32 | dialWidth: 30 33 | startAngle: 180 34 | spanAngle: 70 35 | minValue: 0 36 | maxValue: 100 37 | value: 50 38 | textFont { 39 | family: "Halvetica" 40 | italic: false 41 | pointSize: 16 42 | } 43 | suffixText: "%" 44 | textColor: "#FFFFFF" 45 | } 46 | 47 | RadialBar { 48 | width: 300 49 | height: 300 50 | penStyle: Qt.RoundCap 51 | dialType: RadialBar.FullDial 52 | progressColor: "#c61e5d" 53 | foregroundColor: "#191a2f" 54 | dialWidth: 30 55 | startAngle: 180 56 | spanAngle: 180 57 | minValue: 0 58 | maxValue: 100 59 | value: 80 60 | textFont { 61 | family: "Consolas" 62 | italic: false 63 | pointSize: 32 64 | } 65 | suffixText: "°" 66 | textColor: "#c61e5d" 67 | } 68 | 69 | RadialBar { 70 | width: 300 71 | height: 300 72 | penStyle: Qt.RoundCap 73 | dialType: RadialBar.FullDial 74 | progressColor: "#1e5dc6" 75 | foregroundColor: "#191a2f" 76 | dialWidth: 30 77 | startAngle: 180 78 | spanAngle: 280 79 | minValue: 0 80 | maxValue: 100 81 | value: 68 82 | textFont { 83 | family: "Encode Sans" 84 | italic: false 85 | pointSize: 24 86 | } 87 | suffixText: "%" 88 | textColor: "#1e5dc6" 89 | } 90 | } 91 | 92 | RowLayout { 93 | id: layout1 94 | spacing: 30 95 | RadialBar { 96 | penStyle: Qt.FlatCap 97 | dialType: RadialBar.FullDial 98 | progressColor: "#e67f22" 99 | foregroundColor: "#bec3c7" 100 | dialWidth: 15 101 | startAngle: 180 102 | minValue: 0 103 | maxValue: 100 104 | value: 45 105 | textFont { 106 | family: "Halvetica" 107 | italic: false 108 | pointSize: 22 109 | } 110 | suffixText: "%" 111 | textColor: "#7c8688" 112 | } 113 | 114 | RadialBar { 115 | width: 300 116 | height: 300 117 | penStyle: Qt.FlatCap 118 | dialType: RadialBar.FullDial 119 | progressColor: "#8e42ae" 120 | foregroundColor: "#bec3c7" 121 | dialWidth: 15 122 | startAngle: 180 123 | minValue: 0 124 | maxValue: 100 125 | value: 75 126 | textFont { 127 | family: "Consolas" 128 | italic: false 129 | pointSize: 22 130 | } 131 | suffixText: "°" 132 | textColor: "#7c8688" 133 | } 134 | 135 | RadialBar { 136 | width: 300 137 | height: 300 138 | smooth: true 139 | penStyle: Qt.FlatCap 140 | dialType: RadialBar.FullDial 141 | progressColor: "#e84c3d" 142 | foregroundColor: "#bec3c7" 143 | dialWidth: 15 144 | startAngle: 180 145 | minValue: 0 146 | maxValue: 100 147 | value: 95 148 | textFont { 149 | family: "Encode Sans" 150 | italic: false 151 | pointSize: 32 152 | } 153 | suffixText: "%" 154 | textColor: "#7c8688" 155 | } 156 | } 157 | 158 | RowLayout { 159 | id: layout2 160 | spacing: 30 161 | RadialBar { 162 | width: 300 163 | height: 300 164 | penStyle: Qt.FlatCap 165 | dialType: RadialBar.NoDial 166 | progressColor: "#3498db" 167 | backgroundColor: "#34495e" 168 | dialWidth: 20 169 | startAngle: 0 170 | spanAngle: 270 171 | minValue: 0 172 | maxValue: 100 173 | value: 30 174 | textFont { 175 | family: "Consolas" 176 | italic: false 177 | pointSize: 32 178 | } 179 | suffixText: "%" 180 | textColor: "#FFFFFF" 181 | } 182 | 183 | RadialBar { 184 | width: 300 185 | height: 300 186 | penStyle: Qt.FlatCap 187 | dialType: RadialBar.NoDial 188 | progressColor: "#c61e5d" 189 | backgroundColor: "#34495e" 190 | dialWidth: 20 191 | startAngle: 0 192 | spanAngle: 180 193 | minValue: 0 194 | maxValue: 100 195 | value: 60 196 | textFont { 197 | family: "Consolas" 198 | italic: false 199 | pointSize: 32 200 | } 201 | suffixText: "°" 202 | textColor: "#FFFFFF" 203 | } 204 | 205 | RadialBar { 206 | width: 300 207 | height: 300 208 | penStyle: Qt.FlatCap 209 | dialType: RadialBar.NoDial 210 | progressColor: "#e2801d" 211 | backgroundColor: "#34495e" 212 | dialWidth: 20 213 | startAngle: 0 214 | spanAngle: 320 215 | minValue: 0 216 | maxValue: 100 217 | value: 90 218 | textFont { 219 | family: "Consolas" 220 | italic: false 221 | pointSize: 32 222 | } 223 | suffixText: "%" 224 | textColor: "#FFFFFF" 225 | } 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /main2.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Window 2.2 3 | import CustomControls 1.0 4 | import QtQuick.Controls 2.0 5 | import QtQuick.Controls 1.2 6 | import QtQuick.Layouts 1.1 7 | 8 | ApplicationWindow { 9 | id: appwnd 10 | visible: true 11 | width: 1200 12 | height: 720 13 | title: qsTr("Hello World") 14 | 15 | property int columns : 3 16 | property int rows : 2 17 | 18 | Rectangle { 19 | anchors.fill: parent 20 | color: "#1f225c" 21 | } 22 | 23 | GridView { 24 | id: grid 25 | anchors.fill: parent 26 | cellWidth: Math.max(width / 3, height/3); 27 | cellHeight: Math.max(width / 3, height/3) 28 | model: dashModel 29 | delegate : Rectangle { 30 | Layout.alignment: Layout.Center 31 | width: grid.cellWidth 32 | height: grid.cellHeight 33 | color: "#1d1d35" 34 | border.color: "#000000" 35 | border.width: 3 36 | 37 | Text { 38 | id: name 39 | text: tagName 40 | anchors.left: parent.left 41 | anchors.top: parent.top 42 | anchors.leftMargin: 10 43 | anchors.topMargin: 10 44 | font.pointSize: 13 45 | color: "#FAFAFA" 46 | } 47 | 48 | RadialBar { 49 | anchors.horizontalCenter: parent.horizontalCenter 50 | anchors.bottom: parent.bottom 51 | width: parent.width / 1.4 52 | height: width 53 | penStyle: Qt.RoundCap 54 | progressColor: "#00ffc1" 55 | foregroundColor: "#191a2f" 56 | dialWidth: 12 57 | minValue: minVal 58 | maxValue: maxVal 59 | value: actVal 60 | suffixText: suffix 61 | textFont { 62 | family: "Halvetica" 63 | italic: false 64 | pointSize: 18 65 | } 66 | textColor: "#00ffc1" 67 | } 68 | } 69 | onWidthChanged: { 70 | grid.cellWidth = grid.width/appwnd.columns; 71 | } 72 | 73 | onHeightChanged: { 74 | grid.cellHeight = grid.height/appwnd.rows 75 | } 76 | } 77 | 78 | ListModel { 79 | id: dashModel 80 | ListElement { 81 | tagName: "Temperature" 82 | minVal: 0 83 | maxVal: 100 84 | actVal: 28 85 | suffix: "°" 86 | } 87 | ListElement { 88 | tagName: "Humidity" 89 | minVal: 0 90 | maxVal: 100 91 | actVal: 36 92 | suffix: "%" 93 | } 94 | ListElement { 95 | tagName: "Pressure" 96 | minVal: 0 97 | maxVal: 100 98 | actVal: 56 99 | suffix: " mBar" 100 | } 101 | ListElement { 102 | tagName: "Wind" 103 | minVal: 0 104 | maxVal: 200 105 | actVal: 12 106 | suffix: " MPH" 107 | } 108 | ListElement { 109 | tagName: "Battery" 110 | minVal: 0 111 | maxVal: 15 112 | actVal: 12.65 113 | suffix: " V" 114 | } 115 | ListElement { 116 | tagName: "Load" 117 | minVal: 0 118 | maxVal: 1000 119 | actVal: 425 120 | suffix: " mAmp" 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | main2.qml 5 | radialBarShapeDemo.qml 6 | RadialBarShape.qml 7 | 8 | 9 | -------------------------------------------------------------------------------- /radialBarShapeDemo.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Window 2.2 3 | import CustomControls 1.0 4 | import QtQuick.Controls 2.0 5 | import QtQuick.Controls 1.2 6 | import QtQuick.Layouts 1.1 7 | 8 | Window { 9 | id: root 10 | visible: true 11 | color: "#282a36" 12 | width: 1024 13 | height: 600 14 | title: qsTr("RadialBarShape Demo") 15 | 16 | QtObject { 17 | id: feeder 18 | 19 | property real value: 0 20 | 21 | SequentialAnimation on value { 22 | loops: Animation.Infinite 23 | NumberAnimation { to: 100; duration: 2000 } 24 | NumberAnimation { to: 0; duration: 2000 } 25 | } 26 | } 27 | 28 | ColumnLayout { 29 | anchors.centerIn: parent 30 | spacing: 10 31 | RowLayout { 32 | Layout.fillWidth: true 33 | spacing: 20 34 | RadialBarShape { 35 | value: feeder.value 36 | } 37 | RadialBarShape { 38 | Layout.preferredHeight: 300 39 | Layout.preferredWidth: 300 40 | progressColor: "#e6436d" 41 | value: feeder.value 42 | spanAngle: 270 43 | dialType: RadialBarShape.DialType.FullDial 44 | backgroundColor: "#6272a4" 45 | penStyle: Qt.FlatCap 46 | dialColor: "transparent" 47 | } 48 | RadialBarShape { 49 | progressColor: "#8be9fd" 50 | value: feeder.value 51 | spanAngle: 270 52 | dialType: RadialBarShape.DialType.NoDial 53 | dialColor: Qt.darker("#8be9fd", 3.8) 54 | penStyle: Qt.SquareCap 55 | dialWidth: 10 56 | } 57 | RadialBarShape { 58 | id: newone 59 | progressColor: "#50fa7b" 60 | value: feeder.value 61 | startAngle: 90 62 | spanAngle: 270 63 | dialType: RadialBarShape.DialType.MinToMax 64 | backgroundColor: "#6272a4" 65 | dialWidth: 5 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /radialbar.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************************* 2 | ** The MIT License (MIT) 3 | ** 4 | ** RadialBar is a free Qt and QML based component. 5 | ** Copyright (c) 2017 Arun PK 6 | ** Email: mailztopk@gmail.com 7 | ** 8 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 9 | ** of this software and associated documentation files (the "Software"), to deal 10 | ** in the Software without restriction, including without limitation the rights 11 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | ** copies of the Software, and to permit persons to whom the Software is 13 | ** furnished to do so, subject to the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be included in all 16 | ** copies or substantial portions of the Software. 17 | ** 18 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | ** SOFTWARE. 25 | ************************************************************************************/ 26 | 27 | #include 28 | 29 | #include "radialbar.h" 30 | 31 | RadialBar::RadialBar(QQuickItem *parent) 32 | : QQuickPaintedItem(parent), 33 | m_Size(200), 34 | m_StartAngle(40), 35 | m_SpanAngle(280), 36 | m_MinValue(0), 37 | m_MaxValue(100), 38 | m_Value(50), 39 | m_DialWidth(15), 40 | m_BackgroundColor(Qt::transparent), 41 | m_DialColor(QColor(80,80,80)), 42 | m_ProgressColor(QColor(135,26,5)), 43 | m_TextColor(QColor(0, 0, 0)), 44 | m_SuffixText(""), 45 | m_ShowText(true), 46 | m_PenStyle(Qt::FlatCap), 47 | m_DialType(DialType::MinToMax) 48 | { 49 | setWidth(200); 50 | setHeight(200); 51 | setSmooth(true); 52 | setAntialiasing(true); 53 | } 54 | 55 | void RadialBar::paint(QPainter *painter) 56 | { 57 | double startAngle; 58 | double spanAngle; 59 | qreal size = qMin(this->width(), this->height()); 60 | setWidth(size); 61 | setHeight(size); 62 | QRectF rect = this->boundingRect(); 63 | painter->setRenderHint(QPainter::Antialiasing); 64 | QPen pen = painter->pen(); 65 | pen.setCapStyle(m_PenStyle); 66 | 67 | startAngle = -90 - m_StartAngle; 68 | if(FullDial != m_DialType) 69 | { 70 | spanAngle = 0 - m_SpanAngle; 71 | } 72 | else 73 | { 74 | spanAngle = -360; 75 | } 76 | 77 | //Draw outer dial 78 | painter->save(); 79 | pen.setWidth(m_DialWidth); 80 | pen.setColor(m_DialColor); 81 | painter->setPen(pen); 82 | qreal offset = m_DialWidth / 2; 83 | if(m_DialType == MinToMax) 84 | { 85 | painter->drawArc(rect.adjusted(offset, offset, -offset, -offset), startAngle * 16, spanAngle * 16); 86 | } 87 | else if(m_DialType == FullDial) 88 | { 89 | painter->drawArc(rect.adjusted(offset, offset, -offset, -offset), -90 * 16, -360 * 16); 90 | } 91 | else 92 | { 93 | //do not draw dial 94 | } 95 | painter->restore(); 96 | 97 | //Draw background 98 | painter->save(); 99 | painter->setBrush(m_BackgroundColor); 100 | painter->setPen(m_BackgroundColor); 101 | qreal inner = offset * 2; 102 | painter->drawEllipse(rect.adjusted(inner, inner, -inner, -inner)); 103 | painter->restore(); 104 | 105 | //Draw progress text with suffix 106 | painter->save(); 107 | painter->setFont(m_TextFont); 108 | pen.setColor(m_TextColor); 109 | painter->setPen(pen); 110 | if(m_ShowText) 111 | { 112 | painter->drawText(rect.adjusted(offset, offset, -offset, -offset), Qt::AlignCenter,QString::number(m_Value) + m_SuffixText); 113 | } 114 | else 115 | { 116 | painter->drawText(rect.adjusted(offset, offset, -offset, -offset), Qt::AlignCenter, m_SuffixText); 117 | } 118 | painter->restore(); 119 | 120 | //Draw progress bar 121 | painter->save(); 122 | pen.setWidth(m_DialWidth); 123 | pen.setColor(m_ProgressColor); 124 | qreal valueAngle = ((m_Value - m_MinValue)/(m_MaxValue - m_MinValue)) * spanAngle; //Map value to angle range 125 | painter->setPen(pen); 126 | painter->drawArc(rect.adjusted(offset, offset, -offset, -offset), startAngle * 16, valueAngle * 16); 127 | painter->restore(); 128 | } 129 | 130 | void RadialBar::setSize(qreal size) 131 | { 132 | if(m_Size == size) 133 | return; 134 | m_Size = size; 135 | emit sizeChanged(); 136 | } 137 | 138 | void RadialBar::setStartAngle(qreal angle) 139 | { 140 | if(m_StartAngle == angle) 141 | return; 142 | m_StartAngle = angle; 143 | emit startAngleChanged(); 144 | } 145 | 146 | void RadialBar::setSpanAngle(qreal angle) 147 | { 148 | if(m_SpanAngle == angle) 149 | return; 150 | m_SpanAngle = angle; 151 | emit spanAngleChanged(); 152 | } 153 | 154 | void RadialBar::setMinValue(qreal value) 155 | { 156 | if(m_MinValue == value) 157 | return; 158 | m_MinValue = value; 159 | emit minValueChanged(); 160 | } 161 | 162 | void RadialBar::setMaxValue(qreal value) 163 | { 164 | if(m_MaxValue == value) 165 | return; 166 | m_MaxValue = value; 167 | emit maxValueChanged(); 168 | } 169 | 170 | void RadialBar::setValue(qreal value) 171 | { 172 | if(m_Value == value) 173 | return; 174 | m_Value = value; 175 | update(); //update the radialbar 176 | emit valueChanged(); 177 | } 178 | 179 | void RadialBar::setDialWidth(qreal width) 180 | { 181 | if(m_DialWidth == width) 182 | return; 183 | m_DialWidth = width; 184 | emit dialWidthChanged(); 185 | } 186 | 187 | void RadialBar::setBackgroundColor(QColor color) 188 | { 189 | if(m_BackgroundColor == color) 190 | return; 191 | m_BackgroundColor = color; 192 | emit backgroundColorChanged(); 193 | } 194 | 195 | void RadialBar::setForegroundColor(QColor color) 196 | { 197 | if(m_DialColor == color) 198 | return; 199 | m_DialColor = color; 200 | emit foregroundColorChanged(); 201 | } 202 | 203 | void RadialBar::setProgressColor(QColor color) 204 | { 205 | if(m_ProgressColor == color) 206 | return; 207 | m_ProgressColor = color; 208 | emit progressColorChanged(); 209 | } 210 | 211 | void RadialBar::setTextColor(QColor color) 212 | { 213 | if(m_TextColor == color) 214 | return; 215 | m_TextColor = color; 216 | emit textColorChanged(); 217 | } 218 | 219 | void RadialBar::setSuffixText(QString text) 220 | { 221 | if(m_SuffixText == text) 222 | return; 223 | m_SuffixText = text; 224 | emit suffixTextChanged(); 225 | } 226 | 227 | void RadialBar::setShowText(bool show) 228 | { 229 | if(m_ShowText == show) 230 | return; 231 | m_ShowText = show; 232 | } 233 | 234 | void RadialBar::setPenStyle(Qt::PenCapStyle style) 235 | { 236 | if(m_PenStyle == style) 237 | return; 238 | m_PenStyle = style; 239 | emit penStyleChanged(); 240 | } 241 | 242 | void RadialBar::setDialType(RadialBar::DialType type) 243 | { 244 | if(m_DialType == type) 245 | return; 246 | m_DialType = type; 247 | emit dialTypeChanged(); 248 | } 249 | 250 | void RadialBar::setTextFont(QFont font) 251 | { 252 | if(m_TextFont == font) 253 | return; 254 | m_TextFont = font; 255 | emit textFontChanged(); 256 | } 257 | -------------------------------------------------------------------------------- /radialbar.h: -------------------------------------------------------------------------------- 1 | /************************************************************************************* 2 | ** The MIT License (MIT) 3 | ** 4 | ** RadialBar is a free Qt and QML based component. 5 | ** Copyright (c) 2017 Arun PK 6 | ** Email: mailztopk@gmail.com 7 | ** 8 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 9 | ** of this software and associated documentation files (the "Software"), to deal 10 | ** in the Software without restriction, including without limitation the rights 11 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | ** copies of the Software, and to permit persons to whom the Software is 13 | ** furnished to do so, subject to the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be included in all 16 | ** copies or substantial portions of the Software. 17 | ** 18 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | ** SOFTWARE. 25 | ************************************************************************************/ 26 | 27 | #ifndef RADIALBAR_H 28 | #define RADIALBAR_H 29 | 30 | #include 31 | 32 | class RadialBar : public QQuickPaintedItem 33 | { 34 | Q_OBJECT 35 | 36 | Q_PROPERTY(qreal size READ getSize WRITE setSize NOTIFY sizeChanged) 37 | Q_PROPERTY(qreal startAngle READ getStartAngle WRITE setStartAngle NOTIFY startAngleChanged) 38 | Q_PROPERTY(qreal spanAngle READ getSpanAngle WRITE setSpanAngle NOTIFY spanAngleChanged) 39 | Q_PROPERTY(qreal minValue READ getMinValue WRITE setMinValue NOTIFY minValueChanged) 40 | Q_PROPERTY(qreal maxValue READ getMaxValue WRITE setMaxValue NOTIFY maxValueChanged) 41 | Q_PROPERTY(qreal value READ getValue WRITE setValue NOTIFY valueChanged) 42 | Q_PROPERTY(int dialWidth READ getDialWidth WRITE setDialWidth NOTIFY dialWidthChanged) 43 | Q_PROPERTY(QColor backgroundColor READ getBackgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged) 44 | Q_PROPERTY(QColor foregroundColor READ getForegroundColor WRITE setForegroundColor NOTIFY foregroundColorChanged) 45 | Q_PROPERTY(QColor progressColor READ getProgressColor WRITE setProgressColor NOTIFY progressColorChanged) 46 | Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor NOTIFY textColorChanged) 47 | Q_PROPERTY(QString suffixText READ getSuffixText WRITE setSuffixText NOTIFY suffixTextChanged) 48 | Q_PROPERTY(bool showText READ isShowText WRITE setShowText) 49 | Q_PROPERTY(Qt::PenCapStyle penStyle READ getPenStyle WRITE setPenStyle NOTIFY penStyleChanged) 50 | Q_PROPERTY(DialType dialType READ getDialType WRITE setDialType NOTIFY dialTypeChanged) 51 | Q_PROPERTY(QFont textFont READ getTextFont WRITE setTextFont NOTIFY textFontChanged) 52 | 53 | public: 54 | RadialBar(QQuickItem *parent = 0); 55 | void paint(QPainter *painter); 56 | 57 | enum DialType { 58 | FullDial, 59 | MinToMax, 60 | NoDial 61 | }; 62 | Q_ENUM(DialType) 63 | 64 | qreal getSize() {return m_Size;} 65 | qreal getStartAngle() {return m_StartAngle;} 66 | qreal getSpanAngle() {return m_SpanAngle;} 67 | qreal getMinValue() {return m_MinValue;} 68 | qreal getMaxValue() {return m_MaxValue;} 69 | qreal getValue() {return m_Value;} 70 | int getDialWidth() {return m_DialWidth;} 71 | QColor getBackgroundColor() {return m_BackgroundColor;} 72 | QColor getForegroundColor() {return m_DialColor;} 73 | QColor getProgressColor() {return m_ProgressColor;} 74 | QColor getTextColor() {return m_TextColor;} 75 | QString getSuffixText() {return m_SuffixText;} 76 | bool isShowText() {return m_ShowText;} 77 | Qt::PenCapStyle getPenStyle() {return m_PenStyle;} 78 | DialType getDialType() {return m_DialType;} 79 | QFont getTextFont() {return m_TextFont;} 80 | 81 | void setSize(qreal size); 82 | void setStartAngle(qreal angle); 83 | void setSpanAngle(qreal angle); 84 | void setMinValue(qreal value); 85 | void setMaxValue(qreal value); 86 | void setValue(qreal value); 87 | void setDialWidth(qreal width); 88 | void setBackgroundColor(QColor color); 89 | void setForegroundColor(QColor color); 90 | void setProgressColor(QColor color); 91 | void setTextColor(QColor color); 92 | void setSuffixText(QString text); 93 | void setShowText(bool show); 94 | void setPenStyle(Qt::PenCapStyle style); 95 | void setDialType(DialType type); 96 | void setTextFont(QFont font); 97 | 98 | signals: 99 | void sizeChanged(); 100 | void startAngleChanged(); 101 | void spanAngleChanged(); 102 | void minValueChanged(); 103 | void maxValueChanged(); 104 | void valueChanged(); 105 | void dialWidthChanged(); 106 | void backgroundColorChanged(); 107 | void foregroundColorChanged(); 108 | void progressColorChanged(); 109 | void textColorChanged(); 110 | void suffixTextChanged(); 111 | void penStyleChanged(); 112 | void dialTypeChanged(); 113 | void textFontChanged(); 114 | 115 | private: 116 | qreal m_Size; 117 | qreal m_StartAngle; 118 | qreal m_SpanAngle; 119 | qreal m_MinValue; 120 | qreal m_MaxValue; 121 | qreal m_Value; 122 | int m_DialWidth; 123 | QColor m_BackgroundColor; 124 | QColor m_DialColor; 125 | QColor m_ProgressColor; 126 | QColor m_TextColor; 127 | QString m_SuffixText; 128 | bool m_ShowText; 129 | Qt::PenCapStyle m_PenStyle; 130 | DialType m_DialType; 131 | QFont m_TextFont; 132 | }; 133 | 134 | #endif // RADIALBAR_H 135 | --------------------------------------------------------------------------------