From 6cc3b6c5b21685346151307e2a57e961229c38a6 Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Mon, 3 Sep 2018 10:05:03 +0200 Subject: [PATCH] allow zooming and panning... --- DataService.pro.user | 45 +++++++++++------------ chart.cpp | 47 ++++++++++++++++++++++++ chart.h | 28 +++++++++++++++ chartview.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++++ chartview.h | 25 +++++++++++++ converttoseries.cpp | 8 ++++- converttoseries.h | 2 +- main.cpp | 4 ++- mainwindow.cpp | 58 +++++++++++++++++++++--------- mainwindow.h | 15 ++++---- 10 files changed, 266 insertions(+), 51 deletions(-) create mode 100644 chart.cpp create mode 100644 chart.h create mode 100644 chartview.cpp create mode 100644 chartview.h diff --git a/DataService.pro.user b/DataService.pro.user index b1cea73..1e348ad 100644 --- a/DataService.pro.user +++ b/DataService.pro.user @@ -1,10 +1,10 @@ - + EnvironmentId - {8b523b8d-f5ce-4be4-a9bd-780a0aec766f} + {854dd791-5ef0-48c7-a29e-c0b69b1d5eac} ProjectExplorer.Project.ActiveTarget @@ -59,14 +59,14 @@ ProjectExplorer.Project.Target.0 - Desktop - Desktop - {d7263c99-5355-4486-be71-56523c5d259f} + Qt 5.10.1 (5.10.1) + Qt 5.10.1 (5.10.1) + {3a0db74d-7ece-40c0-8cf4-3c58a6999fdf} 0 0 0 - /home/grewe/zwischenlager/event_queue/build-DataService-Desktop-Debug + /Users/jan/zwischenlager/threading_test/build-DataService-Qt_5_10_1_5_10_1-Debug true @@ -112,7 +112,7 @@ 1 - Clean + Bereinigen ProjectExplorer.BuildSteps.Clean @@ -120,13 +120,13 @@ false Debug - Debug + Qt4ProjectManager.Qt4BuildConfiguration 2 true - /home/grewe/zwischenlager/event_queue/build-DataService-Desktop-Release + /Users/jan/zwischenlager/threading_test/build-DataService-Qt_5_10_1_5_10_1-Release true @@ -172,7 +172,7 @@ 1 - Clean + Bereinigen ProjectExplorer.BuildSteps.Clean @@ -180,13 +180,13 @@ false Release - Release + Qt4ProjectManager.Qt4BuildConfiguration 0 true - /home/grewe/zwischenlager/event_queue/build-DataService-Desktop-Profile + /Users/jan/zwischenlager/threading_test/build-DataService-Qt_5_10_1_5_10_1-Profile true @@ -232,7 +232,7 @@ 1 - Clean + Bereinigen ProjectExplorer.BuildSteps.Clean @@ -240,7 +240,7 @@ false Profile - Profile + Qt4ProjectManager.Qt4BuildConfiguration 0 true @@ -249,12 +249,12 @@ 0 - Deploy + Deployment ProjectExplorer.BuildSteps.Deploy 1 - Deploy Configuration + Lokales Deployment ProjectExplorer.DefaultDeployConfiguration @@ -302,15 +302,12 @@ 2 - DataService + + + %{buildDir} + Benutzerdefinierte ausführbare Datei - Qt4ProjectManager.Qt4RunConfiguration:/home/grewe/zwischenlager/event_queue/DataService/DataService.pro - true - - DataService.pro - false - - /home/grewe/zwischenlager/event_queue/build-DataService-Desktop-Debug + ProjectExplorer.CustomExecutableRunConfiguration 3768 false true diff --git a/chart.cpp b/chart.cpp new file mode 100644 index 0000000..f746bbd --- /dev/null +++ b/chart.cpp @@ -0,0 +1,47 @@ +#include "chart.h" +#include +#include +#include +#include +#include + +Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags) + : QChart(QChart::ChartTypeCartesian, parent, wFlags) +{ + // Seems that QGraphicsView (QChartView) does not grab gestures. + // They can only be grabbed here in the QGraphicsWidget (QChart). + grabGesture(Qt::PinchGesture); + grabGesture(Qt::PanGesture); +} + +Chart::~Chart() { + +} + +bool Chart::sceneEvent(QEvent *event) { + if (event->type() == QEvent::Gesture) + return gestureEvent(static_cast(event)); + return QChart::event(event); +} + +bool Chart::gestureEvent(QGestureEvent *event) { + if (QGesture *gesture = event->gesture(Qt::PanGesture)) { + QPanGesture *pan = static_cast(gesture); + QChart::scroll(-(pan->delta().x()), pan->delta().y()); + } + if (QGesture *gesture = event->gesture(Qt::PinchGesture)) { + QPinchGesture *pinch = static_cast(gesture); + if (pinch->changeFlags() & QPinchGesture::ScaleFactorChanged) + QChart::zoom(pinch->scaleFactor()); + + } + return true; +} + +void Chart::XRangeChanged(qreal min, qreal max) { + std::cerr << "XRangeChanged" << min << "\t"<< max << std::endl; + if (series().at(0)->type() == QtCharts::QAbstractSeries::SeriesTypeLine) { + QLineSeries *s = static_cast(series().at(0)); + std::cerr << s->at(0).x() << "\t"<< s->at(s->count()-1).x() << std::endl; + } +} diff --git a/chart.h b/chart.h new file mode 100644 index 0000000..2ca407d --- /dev/null +++ b/chart.h @@ -0,0 +1,28 @@ +#ifndef CHART_H +#define CHART_H + + +#include + +class QGestureEvent; + +QT_CHARTS_USE_NAMESPACE + +class Chart : public QChart +{ + Q_OBJECT + +public: + explicit Chart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); + ~Chart(); + +protected: + bool sceneEvent(QEvent *event); + +private: + bool gestureEvent(QGestureEvent *event); + +public slots: + void XRangeChanged(qreal min, qreal max); +}; +#endif // CHART_H diff --git a/chartview.cpp b/chartview.cpp new file mode 100644 index 0000000..c0dc152 --- /dev/null +++ b/chartview.cpp @@ -0,0 +1,85 @@ +#include "chartview.h" +#include +#include + +ChartView::ChartView(QChart *chart, QWidget *parent) : + QChartView(chart, parent), + m_isTouching(false) +{ + setRubberBand(QChartView::RectangleRubberBand); + addScrollBarWidget(bar, Qt::AlignBottom); +} + + +bool ChartView::viewportEvent(QEvent *event) +{ + if (event->type() == QEvent::TouchBegin) { + // By default touch events are converted to mouse events. So + // after this event we will get a mouse event also but we want + // to handle touch events as gestures only. So we need this safeguard + // to block mouse events that are actually generated from touch. + m_isTouching = true; + + // Turn off animations when handling gestures they + // will only slow us down. + chart()->setAnimationOptions(QChart::NoAnimation); + } + return QChartView::viewportEvent(event); +} + + +void ChartView::mousePressEvent(QMouseEvent *event) +{ + if (m_isTouching) + return; + QChartView::mousePressEvent(event); +} + + +void ChartView::mouseMoveEvent(QMouseEvent *event) +{ + if (m_isTouching) + return; + QChartView::mouseMoveEvent(event); +} + + +void ChartView::mouseReleaseEvent(QMouseEvent *event) +{ + if (m_isTouching) + m_isTouching = false; + + // Because we disabled animations when touch event was detected + // we must put them back on. + //chart()->setAnimationOptions(QChart::SeriesAnimations); + + QChartView::mouseReleaseEvent(event); +} + + +void ChartView::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Plus: + chart()->zoomIn(); + break; + case Qt::Key_Minus: + chart()->zoomOut(); + break; + case Qt::Key_Left: + chart()->scroll(-10, 0); + break; + case Qt::Key_Right: + chart()->scroll(10, 0); + break; + case Qt::Key_Up: + chart()->scroll(0, 10); + break; + case Qt::Key_Down: + chart()->scroll(0, -10); + break; + default: + QGraphicsView::keyPressEvent(event); + break; + } +} diff --git a/chartview.h b/chartview.h new file mode 100644 index 0000000..fba87b5 --- /dev/null +++ b/chartview.h @@ -0,0 +1,25 @@ +#ifndef CHARTVIEW_H +#define CHARTVIEW_H + +#include +#include + +QT_CHARTS_USE_NAMESPACE + +class ChartView : public QChartView +{ +public: + ChartView(QChart *chart, QWidget *parent = 0); + +protected: + bool viewportEvent(QEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *event); + +private: + bool m_isTouching; +}; + +#endif // CHARTVIEW_H diff --git a/converttoseries.cpp b/converttoseries.cpp index a539292..ad9daa0 100644 --- a/converttoseries.cpp +++ b/converttoseries.cpp @@ -8,11 +8,17 @@ ConvertToSeries::ConvertToSeries(QObject *parent) : QObject(parent) void ConvertToSeries::run() { mutex.lock(); + double min = data.ydata[0]; + double max = data.ydata[0]; if (dataPresent) { for (size_t i = 0; i < data.xdata.size(); ++i) { this->series->append(data.xdata[i], data.ydata[i]); + if (data.ydata[i] < min) + min = data.ydata[i]; + if (data.ydata[i] > max) + max = data.ydata[i]; } - emit dataConverted(series, QString::fromStdString(data.entityId)); + emit dataConverted(series, QString::fromStdString(data.entityId), min, max); } mutex.unlock(); } diff --git a/converttoseries.h b/converttoseries.h index 97d19e5..4af298d 100644 --- a/converttoseries.h +++ b/converttoseries.h @@ -26,7 +26,7 @@ public: void setData(QLineSeries *series, const DataResult1D &data); signals: - void dataConverted(QLineSeries *series, QString entityId); + void dataConverted(QLineSeries *series, QString entityId, double, double); }; diff --git a/main.cpp b/main.cpp index 4cc5943..bf5f1e4 100644 --- a/main.cpp +++ b/main.cpp @@ -8,6 +8,8 @@ int main(int argc, char *argv[]) QApplication a(argc, argv); MainWindow w; w.show(); - + w.grabGesture(Qt::PanGesture); + w.grabGesture(Qt::PinchGesture); + w.grabGesture(Qt::SwipeGesture); return a.exec(); } diff --git a/mainwindow.cpp b/mainwindow.cpp index 05c9ca3..2388b23 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -2,6 +2,8 @@ #include "ui_mainwindow.h" #include "converttoseries.h" #include +#include "chart.h" +#include "chartview.h" using namespace QtCharts; @@ -25,26 +27,26 @@ MainWindow::MainWindow(QWidget *parent) : dataQueue.start(); connect(ui->requestDataBtn, SIGNAL(clicked(bool)), this, SLOT(requestData())); - file = nix::File::open("/home/grewe/zwischenlager/2017-08-17-af-invivo-1/2017-08-17-af-invivo-1.nix", - nix::FileMode::ReadOnly); + //file = nix::File::open("/home/grewe/zwischenlager/2017-08-17-af-invivo-1/2017-08-17-af-invivo-1.nix", + // nix::FileMode::ReadOnly); - //file = nix::File::open("/Users/jan/zwischenlager/threading_test/event_queue/DataService/data/2017-08-17-af-invivo-1.nix", - // nix::FileMode::ReadOnly); + file = nix::File::open("/Users/jan/zwischenlager/threading_test/dataservice/data/2017-08-17-af-invivo-1.nix", + nix::FileMode::ReadOnly); nix::Block b = file.getBlock(0); this->voltage = b.getDataArray("V-1"); this->eod = b.getDataArray("EOD"); - voltageChart = new QChart(); + voltageChart = new Chart(); voltageChart->legend()->hide(); - //voltageChart->createDefaultAxes(); + voltageChart->createDefaultAxes(); - eodChart = new QChart(); + eodChart = new Chart(); eodChart->legend()->hide(); - //eodChart->createDefaultAxes(); + eodChart->createDefaultAxes(); - chartMap.insert(std::pair(voltage.id(), voltageChart)); - chartMap.insert(std::pair(eod.id(), eodChart)); + chartMap.insert(std::pair(voltage.id(), voltageChart)); + chartMap.insert(std::pair(eod.id(), eodChart)); voltageChart->setTitle(QString::fromStdString(this->voltage.name())); eodChart->setTitle(QString::fromStdString(this->eod.name())); @@ -52,9 +54,12 @@ MainWindow::MainWindow(QWidget *parent) : int marg1 = margins.left(); margins.setLeft(marg1 * 4); eodChart->setMargins(margins); - voltageView = new QtCharts::QChartView(voltageChart); - eodView = new QtCharts::QChartView(eodChart); - + voltageView = new ChartView(voltageChart); + //voltageView->setRubberBand(QChartView::HorizontalRubberBand); + voltageView->setLineWidth(1); + eodView = new ChartView(eodChart); + //eodView->setRubberBand(QChartView::HorizontalRubberBand); + eodView->setLineWidth(1); voltageView->setRenderHint(QPainter::Antialiasing); eodView->setRenderHint(QPainter::Antialiasing); ui->vbox->addWidget(voltageView); @@ -83,22 +88,41 @@ void MainWindow::dataReady(QString requestId) { ConvertToSeries *task = new ConvertToSeries(); QLineSeries *series = new QLineSeries(); task->setData(series, data); - connect(task, SIGNAL(dataConverted(QLineSeries*,QString)), this, SLOT(dataConverted(QLineSeries*,QString))); + connect(task, SIGNAL(dataConverted(QLineSeries*,QString, double, double)), this, SLOT(dataConverted(QLineSeries*,QString, double, double))); QThreadPool::globalInstance()->start(task); } -void MainWindow::dataConverted(QLineSeries *series, QString entityId) { +void MainWindow::dataConverted(QLineSeries *series, QString entityId, double ymin, double ymax) { + Chart *chart = chartMap[entityId.toStdString()]; + series->setUseOpenGL(true); + chart->addSeries(series); + + QValueAxis *axisY = new QValueAxis; + double range = ymax - ymin; + axisY->setRange(ymin - 0.2 * range, ymax + 0.2 * range); + axisY->setTickCount(10); + axisY->applyNiceNumbers(); + axisY->setTitleText("Test"); + chart->setAxisY(axisY, series); + + QValueAxis *axisX = new QValueAxis; + axisX->setRange(series->at(0).x(), series->at(series->count()-1).x()); + axisX->setTickCount(10); + axisX->setLabelFormat("%.4f"); + axisX->applyNiceNumbers(); + chart->setAxisX(axisX, series); + connect(axisX, SIGNAL(rangeChanged(qreal,qreal)), chart, SLOT(XRangeChanged(qreal,qreal))); + QPen pen = series->pen(); pen.setWidth(1); series->setPen(pen); - chartMap[entityId.toStdString()]->addSeries(series); } void MainWindow::requestData() { if (voltage && eod) { - nix::NDSize count(1, 10000); + nix::NDSize count(1, 100000); nix::NDSize start(1, 0); std::string vId, eodId; dataQueue.requestData(voltage, count, start, vId); diff --git a/mainwindow.h b/mainwindow.h index 506e7f1..3263ff5 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -2,13 +2,14 @@ #define MAINWINDOW_H #include -//#include #include #include #include "dataservice.h" #include "dataqueue.h" #include "dataresult1d.h" +#include "chart.h" +#include "chartview.h" Q_DECLARE_METATYPE(DataResult1D) @@ -27,7 +28,7 @@ public: public slots: void requestData(); void dataReady(QString requestId); - void dataConverted(QLineSeries *series, QString entityId); + void dataConverted(QLineSeries *series, QString entityId, double ymin, double ymax); private: Ui::MainWindow *ui; @@ -36,11 +37,11 @@ private: DataQueue dataQueue; nix::DataArray voltage, eod; nix::File file; - QtCharts::QChartView *voltageView; - QtCharts::QChartView *eodView; - QtCharts::QChart *voltageChart; - QtCharts::QChart *eodChart; - std::map chartMap; + ChartView *voltageView; + ChartView *eodView; + Chart *voltageChart; + Chart *eodChart; + std::map chartMap; }; #endif // MAINWINDOW_H