├── qml.qrc ├── qtquickcontrols2.conf ├── README.md ├── PlotView.qml ├── plotdata.cpp ├── plotdata.h ├── main.cpp ├── .gitignore ├── main.qml ├── qwtquick2.h ├── qwtquick2.pro ├── LICENSE ├── qwtquick2.cpp └── qwtquick2.pro.user /qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | qtquickcontrols2.conf 5 | PlotView.qml 6 | 7 | 8 | -------------------------------------------------------------------------------- /qtquickcontrols2.conf: -------------------------------------------------------------------------------- 1 | ; This file can be edited to change the style of the application 2 | ; See Styling Qt Quick Controls 2 in the documentation for details: 3 | ; http://doc.qt.io/qt-5/qtquickcontrols2-styles.html 4 | 5 | [Controls] 6 | Style=Material 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qwtquick2 2 | 3 | This is a wrapper to Qwt to render by QtQuick2. Inspired by [qmlplot](https://github.com/mosolovsa/qmlplot) (same thing using QCustomPlot) 4 | 5 | The plot it self is implemented in c++ but can be shown in qml. 6 | 7 | Requirements: 8 | 9 | - Qt 5.x (tested with 5.11) 10 | - Qwt (tested with 6.x) 11 | -------------------------------------------------------------------------------- /PlotView.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QwtQuick2 1.0 3 | 4 | Item { 5 | id: plotForm 6 | 7 | Text { 8 | id: text 9 | text: qsTr("Plot form") 10 | } 11 | 12 | QwtQuick2Plot { 13 | id: qwtPlot 14 | anchors.fill: parent 15 | 16 | Component.onCompleted: initQwtPlot() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /plotdata.cpp: -------------------------------------------------------------------------------- 1 | #include "plotdata.h" 2 | 3 | PlotData::PlotData(const QVector *container) : 4 | _container(container) 5 | { 6 | } 7 | 8 | size_t PlotData::size() const 9 | { 10 | return static_cast(_container->size()); 11 | } 12 | 13 | QPointF PlotData::sample(size_t i) const 14 | { 15 | return _container->at(static_cast(i)); 16 | } 17 | 18 | QRectF PlotData::boundingRect() const 19 | { 20 | return qwtBoundingRect(*this); 21 | } 22 | -------------------------------------------------------------------------------- /plotdata.h: -------------------------------------------------------------------------------- 1 | #ifndef PLOTDATA_H 2 | #define PLOTDATA_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | 10 | class PlotData : public QwtSeriesData 11 | { 12 | public: 13 | PlotData(const QVector *container); 14 | 15 | private: 16 | const QVector* _container; 17 | 18 | // QwtSeriesData interface 19 | public: 20 | size_t size() const; 21 | QPointF sample(size_t i) const; 22 | QRectF boundingRect() const; 23 | }; 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | #endif // PLOTDATA_H 33 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | //#include 3 | #include 4 | #include 5 | 6 | #include "qwtquick2.h" 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | QApplication a(argc, argv); 11 | // QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 12 | // QGuiApplication app(argc, argv); 13 | 14 | qmlRegisterType("QwtQuick2", 1, 0, "QwtQuick2Plot"); 15 | 16 | QQmlApplicationEngine engine; 17 | engine.load(QUrl(QLatin1String("qrc:/main.qml"))); 18 | 19 | return a.exec(); 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | *.slo 3 | *.lo 4 | *.o 5 | *.a 6 | *.la 7 | *.lai 8 | *.so 9 | *.dll 10 | *.dylib 11 | 12 | # Qt-es 13 | object_script.*.Release 14 | object_script.*.Debug 15 | *_plugin_import.cpp 16 | /.qmake.cache 17 | /.qmake.stash 18 | *.pro.user 19 | *.pro.user.* 20 | *.qbs.user 21 | *.qbs.user.* 22 | *.moc 23 | moc_*.cpp 24 | moc_*.h 25 | qrc_*.cpp 26 | ui_*.h 27 | *.qmlc 28 | *.jsc 29 | Makefile* 30 | *build-* 31 | 32 | # Qt unit tests 33 | target_wrapper.* 34 | 35 | # QtCreator 36 | *.autosave 37 | 38 | # QtCreator Qml 39 | *.qmlproject.user 40 | *.qmlproject.user.* 41 | 42 | # QtCreator CMake 43 | CMakeLists.txt.user* 44 | -------------------------------------------------------------------------------- /main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.0 4 | 5 | ApplicationWindow { 6 | visible: true 7 | width: 640 8 | height: 480 9 | title: qsTr("Hello QWT in QML") 10 | 11 | // Item { 12 | // id: mainView 13 | // anchors.fill: parent 14 | // PlotView { 15 | // } 16 | // } 17 | SwipeView { 18 | id: swipeView 19 | anchors.fill: parent 20 | currentIndex: tabBar.currentIndex 21 | interactive: false 22 | 23 | PlotView { 24 | } 25 | 26 | Page { 27 | Label { 28 | text: qsTr("Adding random data on 500 ms tick to plot") 29 | anchors.centerIn: parent 30 | } 31 | } 32 | } 33 | 34 | footer: TabBar { 35 | id: tabBar 36 | currentIndex: swipeView.currentIndex 37 | TabButton { 38 | text: qsTr("Plot") 39 | } 40 | TabButton { 41 | text: qsTr("Info") 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /qwtquick2.h: -------------------------------------------------------------------------------- 1 | #ifndef QMLPLOT_H 2 | #define QMLPLOT_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | class QwtQuick2Plot : public QQuickPaintedItem 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | QwtQuick2Plot(QQuickItem* parent = nullptr); 15 | virtual ~QwtQuick2Plot(); 16 | 17 | void paint(QPainter* painter); 18 | 19 | Q_INVOKABLE void initQwtPlot(); 20 | 21 | protected: 22 | void routeMouseEvents(QMouseEvent* event); 23 | void routeWheelEvents(QWheelEvent* event); 24 | 25 | virtual void mousePressEvent(QMouseEvent* event); 26 | virtual void mouseReleaseEvent(QMouseEvent* event); 27 | virtual void mouseMoveEvent(QMouseEvent* event); 28 | virtual void mouseDoubleClickEvent(QMouseEvent* event); 29 | virtual void wheelEvent(QWheelEvent *event); 30 | 31 | virtual void timerEvent(QTimerEvent *event); 32 | 33 | private: 34 | QwtPlot* m_qwtPlot; 35 | QwtPlotCurve* m_curve1; 36 | QVector m_curve1_data; 37 | int m_timerId; 38 | 39 | void replotAndUpdate(); 40 | 41 | private slots: 42 | void updatePlotSize(); 43 | 44 | }; 45 | 46 | #endif // QMLPLOT_H 47 | -------------------------------------------------------------------------------- /qwtquick2.pro: -------------------------------------------------------------------------------- 1 | QT += qml quick core gui printsupport 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 | 5 | CONFIG += c++11 6 | CONFIG += qwt 7 | 8 | SOURCES += main.cpp \ 9 | qwtquick2.cpp \ 10 | plotdata.cpp 11 | 12 | RESOURCES += qml.qrc 13 | 14 | # Additional import path used to resolve QML modules in Qt Creators code model 15 | QML_IMPORT_PATH = 16 | 17 | # Additional import path used to resolve QML modules just for Qt Quick Designer 18 | QML_DESIGNER_IMPORT_PATH = 19 | 20 | # The following define makes your compiler emit warnings if you use 21 | # any feature of Qt which as been marked deprecated (the exact warnings 22 | # depend on your compiler). Please consult the documentation of the 23 | # deprecated API in order to know how to port your code away from it. 24 | DEFINES += QT_DEPRECATED_WARNINGS 25 | 26 | # You can also make your code fail to compile if you use deprecated APIs. 27 | # In order to do so, uncomment the following line. 28 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 29 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 30 | 31 | HEADERS += \ 32 | qwtquick2.h \ 33 | plotdata.h 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /qwtquick2.cpp: -------------------------------------------------------------------------------- 1 | #include "plotdata.h" 2 | #include "qwtquick2.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | QwtQuick2Plot::QwtQuick2Plot(QQuickItem* parent) : QQuickPaintedItem(parent) 11 | , m_qwtPlot(nullptr), m_timerId(0) 12 | { 13 | setFlag(QQuickItem::ItemHasContents, true); 14 | setAcceptedMouseButtons(Qt::AllButtons); 15 | 16 | connect(this, &QQuickPaintedItem::widthChanged, this, &QwtQuick2Plot::updatePlotSize); 17 | connect(this, &QQuickPaintedItem::heightChanged, this, &QwtQuick2Plot::updatePlotSize); 18 | } 19 | 20 | QwtQuick2Plot::~QwtQuick2Plot() 21 | { 22 | delete m_qwtPlot; 23 | m_qwtPlot = nullptr; 24 | 25 | if (m_timerId != 0) { 26 | killTimer(m_timerId); 27 | } 28 | } 29 | 30 | void QwtQuick2Plot::replotAndUpdate() 31 | { 32 | m_qwtPlot->replot(); 33 | update(); 34 | } 35 | 36 | void QwtQuick2Plot::initQwtPlot() 37 | { 38 | m_qwtPlot = new QwtPlot(); 39 | // after replot() we need to call update() - so disable auto replot 40 | m_qwtPlot->setAutoReplot(false); 41 | m_qwtPlot->setStyleSheet("background: white"); 42 | 43 | updatePlotSize(); 44 | 45 | m_curve1 = new QwtPlotCurve("Curve 1"); 46 | 47 | m_curve1->setPen(QPen(Qt::red)); 48 | m_curve1->setStyle(QwtPlotCurve::Lines); 49 | m_curve1->setRenderHint(QwtPlotItem::RenderAntialiased); 50 | 51 | m_curve1->setData(new PlotData(&m_curve1_data)); 52 | 53 | m_qwtPlot->setAxisTitle(m_qwtPlot->xBottom, tr("t")); 54 | m_qwtPlot->setAxisTitle(m_qwtPlot->yLeft, tr("S")); 55 | 56 | m_curve1->attach(m_qwtPlot); 57 | 58 | startTimer(500); 59 | 60 | replotAndUpdate(); 61 | } 62 | 63 | 64 | void QwtQuick2Plot::paint(QPainter* painter) 65 | { 66 | if (m_qwtPlot) { 67 | QPixmap picture(boundingRect().size().toSize()); 68 | 69 | QwtPlotRenderer renderer; 70 | renderer.renderTo(m_qwtPlot, picture); 71 | 72 | painter->drawPixmap(QPoint(), picture); 73 | } 74 | } 75 | 76 | void QwtQuick2Plot::mousePressEvent(QMouseEvent* event) 77 | { 78 | qDebug() << Q_FUNC_INFO; 79 | routeMouseEvents(event); 80 | } 81 | 82 | void QwtQuick2Plot::mouseReleaseEvent(QMouseEvent* event) 83 | { 84 | qDebug() << Q_FUNC_INFO; 85 | routeMouseEvents(event); 86 | } 87 | 88 | void QwtQuick2Plot::mouseMoveEvent(QMouseEvent* event) 89 | { 90 | routeMouseEvents(event); 91 | } 92 | 93 | void QwtQuick2Plot::mouseDoubleClickEvent(QMouseEvent* event) 94 | { 95 | qDebug() << Q_FUNC_INFO; 96 | routeMouseEvents(event); 97 | } 98 | 99 | void QwtQuick2Plot::wheelEvent(QWheelEvent* event) 100 | { 101 | routeWheelEvents(event); 102 | } 103 | 104 | void QwtQuick2Plot::timerEvent(QTimerEvent* /*event*/) 105 | { 106 | static double t, U; 107 | U = (static_cast(qrand()) / RAND_MAX) * 5; 108 | 109 | m_curve1_data.append(QPointF(t, U)); 110 | 111 | qDebug() << Q_FUNC_INFO << QString("Adding dot t = %1, S = %2").arg(t).arg(U); 112 | t++; 113 | replotAndUpdate(); 114 | } 115 | 116 | void QwtQuick2Plot::routeMouseEvents(QMouseEvent* event) 117 | { 118 | if (m_qwtPlot) { 119 | QMouseEvent* newEvent = new QMouseEvent(event->type(), event->localPos(), 120 | event->button(), event->buttons(), 121 | event->modifiers()); 122 | QCoreApplication::postEvent(m_qwtPlot, newEvent); 123 | } 124 | } 125 | 126 | void QwtQuick2Plot::routeWheelEvents(QWheelEvent* event) 127 | { 128 | if (m_qwtPlot) { 129 | QWheelEvent* newEvent = new QWheelEvent(event->pos(), event->delta(), 130 | event->buttons(), event->modifiers(), 131 | event->orientation()); 132 | QCoreApplication::postEvent(m_qwtPlot, newEvent); 133 | } 134 | } 135 | 136 | void QwtQuick2Plot::updatePlotSize() 137 | { 138 | if (m_qwtPlot) { 139 | m_qwtPlot->setGeometry(0, 0, static_cast(width()), static_cast(height())); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /qwtquick2.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {864aab5c-03ce-4e72-b615-2f53bd11c95a} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | true 60 | 61 | 62 | 63 | ProjectExplorer.Project.Target.0 64 | 65 | Desktop 66 | Desktop 67 | {b8c177b3-2345-4c44-8408-2b94c0cdee8e} 68 | 0 69 | 0 70 | 0 71 | 72 | /home/loeppel/Devel/microtap/build-qwt-quickpainted-Desktop-Debug 73 | 74 | 75 | true 76 | qmake 77 | 78 | QtProjectManager.QMakeBuildStep 79 | true 80 | 81 | false 82 | false 83 | false 84 | 85 | 86 | true 87 | Make 88 | 89 | Qt4ProjectManager.MakeStep 90 | 91 | -w 92 | -r 93 | 94 | false 95 | 96 | 97 | 98 | 2 99 | Erstellen 100 | 101 | ProjectExplorer.BuildSteps.Build 102 | 103 | 104 | 105 | true 106 | Make 107 | 108 | Qt4ProjectManager.MakeStep 109 | 110 | -w 111 | -r 112 | 113 | true 114 | clean 115 | 116 | 117 | 1 118 | Bereinigen 119 | 120 | ProjectExplorer.BuildSteps.Clean 121 | 122 | 2 123 | false 124 | 125 | Debug 126 | Debug 127 | Qt4ProjectManager.Qt4BuildConfiguration 128 | 2 129 | true 130 | 131 | 132 | /home/loeppel/Devel/microtap/build-qwt-quickpainted-Desktop-Release 133 | 134 | 135 | true 136 | qmake 137 | 138 | QtProjectManager.QMakeBuildStep 139 | false 140 | 141 | false 142 | false 143 | true 144 | 145 | 146 | true 147 | Make 148 | 149 | Qt4ProjectManager.MakeStep 150 | 151 | -w 152 | -r 153 | 154 | false 155 | 156 | 157 | 158 | 2 159 | Erstellen 160 | 161 | ProjectExplorer.BuildSteps.Build 162 | 163 | 164 | 165 | true 166 | Make 167 | 168 | Qt4ProjectManager.MakeStep 169 | 170 | -w 171 | -r 172 | 173 | true 174 | clean 175 | 176 | 177 | 1 178 | Bereinigen 179 | 180 | ProjectExplorer.BuildSteps.Clean 181 | 182 | 2 183 | false 184 | 185 | Release 186 | Release 187 | Qt4ProjectManager.Qt4BuildConfiguration 188 | 0 189 | true 190 | 191 | 192 | /home/loeppel/Devel/microtap/build-qwt-quickpainted-Desktop-Profile 193 | 194 | 195 | true 196 | qmake 197 | 198 | QtProjectManager.QMakeBuildStep 199 | true 200 | 201 | false 202 | true 203 | true 204 | 205 | 206 | true 207 | Make 208 | 209 | Qt4ProjectManager.MakeStep 210 | 211 | -w 212 | -r 213 | 214 | false 215 | 216 | 217 | 218 | 2 219 | Erstellen 220 | 221 | ProjectExplorer.BuildSteps.Build 222 | 223 | 224 | 225 | true 226 | Make 227 | 228 | Qt4ProjectManager.MakeStep 229 | 230 | -w 231 | -r 232 | 233 | true 234 | clean 235 | 236 | 237 | 1 238 | Bereinigen 239 | 240 | ProjectExplorer.BuildSteps.Clean 241 | 242 | 2 243 | false 244 | 245 | Profile 246 | Profile 247 | Qt4ProjectManager.Qt4BuildConfiguration 248 | 0 249 | true 250 | 251 | 3 252 | 253 | 254 | 0 255 | Deployment 256 | 257 | ProjectExplorer.BuildSteps.Deploy 258 | 259 | 1 260 | Deployment-Konfiguration 261 | 262 | ProjectExplorer.DefaultDeployConfiguration 263 | 264 | 1 265 | 266 | 267 | false 268 | false 269 | 1000 270 | 271 | true 272 | 273 | false 274 | false 275 | false 276 | false 277 | true 278 | 0.01 279 | 10 280 | true 281 | 1 282 | 25 283 | 284 | 1 285 | true 286 | false 287 | true 288 | valgrind 289 | 290 | 0 291 | 1 292 | 2 293 | 3 294 | 4 295 | 5 296 | 6 297 | 7 298 | 8 299 | 9 300 | 10 301 | 11 302 | 12 303 | 13 304 | 14 305 | 306 | 2 307 | 308 | qwt-quickpainted 309 | 310 | Qt4ProjectManager.Qt4RunConfiguration:/home/loeppel/Devel/microtap/qwt-quickpainted/qwt-quickpainted.pro 311 | true 312 | 313 | qwt-quickpainted.pro 314 | 315 | /home/loeppel/Devel/microtap/build-qwt-quickpainted-Desktop-Debug 316 | 3768 317 | false 318 | true 319 | false 320 | false 321 | true 322 | 323 | 1 324 | 325 | 326 | 327 | ProjectExplorer.Project.TargetCount 328 | 1 329 | 330 | 331 | ProjectExplorer.Project.Updater.FileVersion 332 | 18 333 | 334 | 335 | Version 336 | 18 337 | 338 | 339 | --------------------------------------------------------------------------------