Aggiornamento dati
-
Buongiorno a tutti,
sto cercando di inserire dei dati, in un grafico a dispersione, ogni volta che sono disponibili nella Queue. Quando eseguo il programma però i punti non vengono plottati sul grafico. Riuscite ad aiutarmi a risolvere questo problema? Di sotto riporto il codice che ho scritto.
Un grazie in anticipoN.B. la funzione estrai_dati riceve una stringa di dati e ne ricava tre float xpos, ypos e zpos, che sono i dati che verranno plottati in seguito
#include <QtDataVisualization> #include <QtWidgets> #include <QDialog> #include <QtCore> #include <stdio.h> #include <stdlib.h> #include "mygrafic3d.h" #define LIMITE 10 #define DIM 10 #define EPSILON 0.02 #define G 9.81 #define T 1000 using namespace QtDataVisualization; mygrafic3d::mygrafic3d(Q3DScatter *scatter) : m_graph(scatter), m_fontSize(40.0f), m_style(QAbstract3DSeries::MeshSphere), m_smooth(true), m_array(0), m_series(new QScatter3DSeries)/*, inizio(0.0f), fine(100.0f)*/ { //Modifiche visive m_graph->activeTheme()->setType(Q3DTheme::ThemeQt); QFont font = m_graph->activeTheme()->font(); font.setPointSize(m_fontSize); m_graph->activeTheme()->setFont(font); m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftLow); m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront); m_graph->axisX()->setTitle("X"); m_graph->axisY()->setTitle("Y"); m_graph->axisZ()->setTitle("Z"); m_graph->axisX()->setTitleVisible(true); m_graph->axisY()->setTitleVisible(true); m_graph->axisZ()->setTitleVisible(true); //creo un QScatterDataProxy e il QScatter3DSeries associato QScatterDataProxy *proxy = new QScatterDataProxy; m_series = new QScatter3DSeries(proxy); m_series->setItemLabelFormat(QStringLiteral("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel")); m_series->setMeshSmooth(m_smooth); m_graph->addSeries(m_series); qDebug()<< "Parte la queque!"; consume(); qDebug()<< "fuori dalla queque!"; } mygrafic3d::~mygrafic3d() { delete m_graph; } void mygrafic3d::consume() { for(;;) { qDebug()<< "Dentro Queque!"; m_QueueMutex.lock(); qDebug()<< "Dentro Queque lock!"; while (m_Queue.isEmpty()) { m_WaitAnyItem.wait(&m_QueueMutex); } QByteArray mykeypass = m_Queue.first(); m_Queue.removeFirst(); m_QueueMutex.unlock(); if (*mykeypass == NULL) { break; } qDebug()<< "Chiama funzioni"; estrai_dati(mykeypass); addData(); } } void mygrafic3d::addData() { //m_series->dataProxy()->addItem(QVector3D (xpos, ypos, zpos)); m_array = new QScatterDataArray; int arraysize = 100; if (arraysize != m_array->size()) m_array->resize(arraysize); QScatterDataItem *ptrToDataArray = &m_array->first(); ptrToDataArray->setPosition(QVector3D(xpos, ypos, zpos)); ptrToDataArray++; m_series->dataProxy()->resetArray(m_array); }
-
Se ho capito bene devo eliminare la funzione consume() e al suo posto usare il signal/slot e successivamente chiamare estrai_dati() e addData()?
Domanda la funzione addData() è corretta per plottare i dati (xpos, ypos e zpos) sul grafico ogni volta che mi arrivano?
-
@Lorenz_95 said in Aggiornamento dati:
Se ho capito bene devo eliminare la funzione consume() e al suo posto usare il signal/slot e successivamente chiamare estrai_dati() e addData()?
Corretto
Domanda la funzione addData() è corretta per plottare i dati (xpos, ypos e zpos) sul grafico ogni volta che mi arrivano?
si e no. E giusto il concetto ma non l'esecuzione. Tu al momento crei un nuovo array ogni volta, imposti l'ultimo valore (lasciando gli altri non definiti) e poi lo rimetti dentro al grafico. Quello che dovresti fare invece e' estrarre l'array vecchio (
m_series->dataProxy()->array()
) e aggiungere a quello il nuovo dato e poi chiamareresetArray
-
Quindi l'array lo imposto una volta prima della chiamata di addData() e poi inserisco i nuovi valori. Se ho capito bene il codice lo devo modificare così?
// Prima della chiamata di addData m_array = new QScatterDataArray; //funzione addData void mygrafic3d::addData() { int arraysize = 100; if (arraysize != m_array->size()) m_array->resize(arraysize); QScatterDataItem *ptrToDataArray = &m_array->first(); m_series->dataProxy()->array(); ptrToDataArray->setPosition(QVector3D(xpos, ypos, zpos)); ptrToDataArray++; m_series->dataProxy()->resetArray(m_array); }
-
quasi.
// Prima della chiamata di addData m_series->dataProxy()->resetArray( new QScatterDataArray);
void mygrafic3d::addData() { QScatterDataArray* array = m_series->dataProxy()->array(); array->append(QScatterDataItem(QVector3D(xpos, ypos, zpos))); m_series->dataProxy()->resetArray(array ); }
-
@Lorenz_95 said in Aggiornamento dati:
Quindi ogni volta che mi arriva un dato eseguo la connect()
No.
connect
va chiamato una volta sola. crea un ponte tra un segnale e uno slot. in pratica connect dice "quando succede X fai Y". Ogni volta che ricevi un dato devi emettere un segnale (X) e in automatico verra' chiamato Y -
Quindi
connect()
viene chiamata nella classe dove eseguo le modifiche del dato che cambia. Nel mio caso la sostituisco al posto diconsume()
.
Dovrei usarla così nel mio caso? Dove "mykeypass" è un QByteArray mentre "cambiadato" è il segnale che viene emesso quando cambia il valore di "mykeypass" e sono entrambi definiti nella classe dove cambia il dato.connect(mykeypass, SIGNAL(cambiadato(const QByteArray &)), this, SLOT(estrai_dati(const QByteArray &)));
-
@VRonin said in Aggiornamento dati:
// Prima della chiamata di addData
m_series->dataProxy()->resetArray( new QScatterDataArray);void mygrafic3d::addData()
{
QScatterDataArray* array = m_series->dataProxy()->array();
array->append(QScatterDataItem(QVector3D(xpos, ypos, zpos)));
m_series->dataProxy()->resetArray(array );
}Il compilatore mi da errore in questa funzione, dicendo che:
*****"error: cannot initialize a variable of type 'QtDataVisualization::QScatterDataArray *' (aka 'QVector<QtDataVisualization::QScatterDataItem> *') with an rvalue of type 'const QtDataVisualization::QScatterDataArray *' (aka 'const QVector<QtDataVisualization::QScatterDataItem> *')"***** **error: invalid conversion from 'const QScatterDataArray* {aka const QVector<QtDataVisualization::QScatterDataItem>*}' to 'QtDataVisualization::QScatterDataArray* {aka QVector<QtDataVisualization::QScatterDataItem>*}' [-fpermissive] QScatterDataArray *array = m_series->dataProxy()->array(); ^**
Io nel file .h ho già definito
private: QScatterDataArray *m_array;
questo può essere causa dell errore? Come modifico il codice che mi hai scritto? -
no, e' solo un problema di
const
ness:void mygrafic3d::addData() { QScatterDataArray* array = new QScatterDataArray(*m_series->dataProxy()->array()); m_series->dataProxy()->resetArray(Q_NULLPTR); array->append(QScatterDataItem(QVector3D(xpos, ypos, zpos))); m_series->dataProxy()->resetArray(array ); }
-
#include <QtDataVisualization> #include <QtWidgets> #include <QDialog> #include <QtCore> #include <QObject> #include <stdio.h> #include <stdlib.h> #include "mygrafic3d.h" #include "myserver.h" using namespace QtDataVisualization; mygrafic3d::mygrafic3d(Q3DScatter *scatter) : m_graph(scatter), m_fontSize(40.0f), m_style(QAbstract3DSeries::MeshSphere), m_smooth(true), m_series(new QScatter3DSeries)/*, m_array(new QScatterDataArray)*/ { //Modifiche visive m_graph->activeTheme()->setType(Q3DTheme::ThemeQt); QFont font = m_graph->activeTheme()->font(); font.setPointSize(m_fontSize); m_graph->activeTheme()->setFont(font); m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftLow); m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront); m_graph->axisX()->setTitle("X"); m_graph->axisY()->setTitle("Y"); m_graph->axisZ()->setTitle("Z"); m_graph->axisX()->setTitleVisible(true); m_graph->axisY()->setTitleVisible(true); m_graph->axisZ()->setTitleVisible(true); //creo un QScatterDataProxy e il QScatter3DSeries associato QScatterDataProxy *proxy = new QScatterDataProxy; m_series = new QScatter3DSeries(proxy); m_series->setItemLabelFormat(QStringLiteral("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel")); m_series->setMeshSmooth(m_smooth); m_graph->addSeries(m_series); // Prima della chiamata di addData m_series->dataProxy()->resetArray(new QScatterDataArray); connect(&server, SIGNAL(Signal_Data(const QByteArray &)), this, SLOT(slot_data(const QByteArray &))); qDebug() << "segnale ricevuto"; } mygrafic3d::~mygrafic3d() { delete m_graph; } void mygrafic3d::slot_data(const QByteArray &stringa) { strcpy(dato, stringa); qDebug()<< "Valore dato: " << dato; estrai_dati(); addData(); } void mygrafic3d::addData() { QScatterDataArray* array = new QScatterDataArray(*m_series->dataProxy()->array()); m_series->dataProxy()->resetArray(Q_NULLPTR); array->append(QScatterDataItem(QVector3D(xpos, ypos, zpos))); m_series->dataProxy()->resetArray(array); }
In definitiva quello che ho scritto adesso è questo, dovrebbe essere tutto corretto.
Il mio unico dubbio è se ho scritto correttamente laconnect()
perchè non l avevo mai usata prima, potreste dargli un occhio? -
usa la connect di Qt5 cosi' non rischi typos.
ServerClass
qui e' il tipo diserver
.connect(&server, &ServerClass::Signal_Data, this, &mygrafic3d::slot_data);
-
void mygrafic3d::addData() { QScatterDataArray* array = new QScatterDataArray(*m_series->dataProxy()->array()); m_series->dataProxy()->resetArray(Q_NULLPTR); array->append(QScatterDataItem(QVector3D(xpos, ypos, zpos))); m_series->dataProxy()->resetArray(array ); }
Ma in questa funzione non manca una funzione per plottare i dati sul grafico? Come ad esempio
addSeries()
?