Hello!
I'm having a problem about passing Qwt to a Object-oriented language style in my software. Let me explain.
My goal, now, is to create a software which receives data from a socket client, "translate it" and pass the y coordinates to three graphs simultaneously. in fact, I already have this software and it works fine.
The problem is that it is not written in traditional c++ object oriented style when it comes about using Qwt to create the 3 graphs, i.e. the instantiation of each graph is done "manually", not by simply creating the object from a class that create graphs.
So what I have today in my MainWindow, where the creation of the graphs is called, is this:
void MainWindow::on_Start_released()
{
ui->cmd->append("Start");
plot->setParent(ui->grafico); //Liga o grafico à widget
//Dimensões do gráfico dentro do widget
plot->setGeometry(0,0,1020,200);
plot
->setAxisScale
(QwtPlot::yLeft,
0,
300);
plot
->setAxisScale
(QwtPlot::xBottom,
0.0,
150);
//plot->setAxisTitle(QwtPlot::xBottom, "Tempo [s]"); //Falta espaço. Tentar colocar na borda do eixo, não embaixo
//plot->setAxisScale(QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue()); //faz a mudança dos números no eixo X
//Coloca grid
grid
->setPen
(QPen(Qt
::gray,
0.0, Qt
::DotLine));
grid->enableX(true);
grid->enableXMin(true);
grid->enableY(true);
grid->enableYMin(false);
grid->attach(plot);
//plot->axisAutoScale(1);
//plot->axisAutoScale(1);
plot->show();
curva
->setPen
(QPen(Qt
::green));
//Cor da linha do gráfico (Cada um com sua cor?) curva->attach(plot);
/*******************************************************/
plot2->setParent(ui->grafico2); //Liga o grafico à widget
//Dimensões do gráfico dentro do widget
plot2->setGeometry(0,0,1020,200);
plot2
->setAxisScale
(QwtPlot::yLeft,
0,
300);
plot2
->setAxisScale
(QwtPlot::xBottom,
0.0,
150);
//plot->setAxisTitle(QwtPlot::xBottom, "Tempo [s]"); //Falta espaço. Tentar colocar na borda do eixo, não embaixo
//plot->setAxisScale(QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue()); //faz a mudança dos números no eixo X
//Coloca grid
grid2
->setPen
(QPen(Qt
::gray,
0.0, Qt
::DotLine));
grid2->enableX(true);
grid2->enableXMin(true);
grid2->enableY(true);
grid2->enableYMin(false);
grid2->attach(plot2);
//plot->axisAutoScale(1);
//plot->axisAutoScale(1);
plot2->show();
curva2
->setPen
(QPen(Qt
::green));
//Cor da linha do gráfico (Cada um com sua cor?) curva2->attach(plot2);
/*******************************************************/
plot3->setParent(ui->grafico3); //Liga o grafico à widget
//Dimensões do gráfico dentro do widget
plot3->setGeometry(0,0,1020,200);
plot3
->setAxisScale
(QwtPlot::yLeft,
0,
300);
plot3
->setAxisScale
(QwtPlot::xBottom,
0.0,
150);
//plot->setAxisTitle(QwtPlot::xBottom, "Tempo [s]"); //Falta espaço. Tentar colocar na borda do eixo, não embaixo
//plot->setAxisScale(QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue()); //faz a mudança dos números no eixo X
//Coloca grid
grid3
->setPen
(QPen(Qt
::gray,
0.0, Qt
::DotLine));
grid3->enableX(true);
grid3->enableXMin(true);
grid3->enableY(true);
grid3->enableYMin(false);
grid3->attach(plot3);
//plot->axisAutoScale(1);
//plot->axisAutoScale(1);
plot3->show();
curva3
->setPen
(QPen(Qt
::green));
//Cor da linha do gráfico (Cada um com sua cor?) curva3->attach(plot3);
Server.StartServer();
}
void MainWindow::on_Start_released()
{
ui->cmd->append("Start");
plot = new QwtPlot(QwtText("Graph 1"));
plot->setParent(ui->grafico); //Liga o grafico à widget
//Dimensões do gráfico dentro do widget
plot->setGeometry(0,0,1020,200);
plot->setAxisScale(QwtPlot::yLeft,0,300);
plot->setAxisScale(QwtPlot::xBottom,0.0,150);
//plot->setAxisTitle(QwtPlot::xBottom, "Tempo [s]"); //Falta espaço. Tentar colocar na borda do eixo, não embaixo
//plot->setAxisScale(QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue()); //faz a mudança dos números no eixo X
//Coloca grid
QwtPlotGrid *grid = new QwtPlotGrid();
grid->setPen(QPen(Qt::gray, 0.0, Qt::DotLine));
grid->enableX(true);
grid->enableXMin(true);
grid->enableY(true);
grid->enableYMin(false);
grid->attach(plot);
//plot->axisAutoScale(1);
//plot->axisAutoScale(1);
plot->show();
curva = new QwtPlotCurve("ECG"); //Antes: "Sine"
curva->setStyle(QwtPlotCurve::Lines);
curva->setPen(QPen(Qt::green)); //Cor da linha do gráfico (Cada um com sua cor?)
curva->attach(plot);
/*******************************************************/
plot2 = new QwtPlot(QwtText("Graph 2"));
plot2->setParent(ui->grafico2); //Liga o grafico à widget
//Dimensões do gráfico dentro do widget
plot2->setGeometry(0,0,1020,200);
plot2->setAxisScale(QwtPlot::yLeft,0,300);
plot2->setAxisScale(QwtPlot::xBottom,0.0,150);
//plot->setAxisTitle(QwtPlot::xBottom, "Tempo [s]"); //Falta espaço. Tentar colocar na borda do eixo, não embaixo
//plot->setAxisScale(QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue()); //faz a mudança dos números no eixo X
//Coloca grid
QwtPlotGrid *grid2 = new QwtPlotGrid();
grid2->setPen(QPen(Qt::gray, 0.0, Qt::DotLine));
grid2->enableX(true);
grid2->enableXMin(true);
grid2->enableY(true);
grid2->enableYMin(false);
grid2->attach(plot2);
//plot->axisAutoScale(1);
//plot->axisAutoScale(1);
plot2->show();
curva2 = new QwtPlotCurve("ECG"); //Antes: "Sine"
curva2->setStyle(QwtPlotCurve::Lines);
curva2->setPen(QPen(Qt::green)); //Cor da linha do gráfico (Cada um com sua cor?)
curva2->attach(plot2);
/*******************************************************/
plot3 = new QwtPlot(QwtText("Graph 3"));
plot3->setParent(ui->grafico3); //Liga o grafico à widget
//Dimensões do gráfico dentro do widget
plot3->setGeometry(0,0,1020,200);
plot3->setAxisScale(QwtPlot::yLeft,0,300);
plot3->setAxisScale(QwtPlot::xBottom,0.0,150);
//plot->setAxisTitle(QwtPlot::xBottom, "Tempo [s]"); //Falta espaço. Tentar colocar na borda do eixo, não embaixo
//plot->setAxisScale(QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue()); //faz a mudança dos números no eixo X
//Coloca grid
QwtPlotGrid *grid3 = new QwtPlotGrid();
grid3->setPen(QPen(Qt::gray, 0.0, Qt::DotLine));
grid3->enableX(true);
grid3->enableXMin(true);
grid3->enableY(true);
grid3->enableYMin(false);
grid3->attach(plot3);
//plot->axisAutoScale(1);
//plot->axisAutoScale(1);
plot3->show();
curva3 = new QwtPlotCurve("ECG"); //Antes: "Sine"
curva3->setStyle(QwtPlotCurve::Lines);
curva3->setPen(QPen(Qt::green)); //Cor da linha do gráfico (Cada um com sua cor?)
curva3->attach(plot3);
Server.StartServer();
}
To copy to clipboard, switch view to plain text mode
(Sorry for the Portuguese comments, by I imagine that you will understand the code anyway ;] )
So as you can see, I have to create each of the 3 graphs manually, which is not the OO style. And I want, therefore, to transform that code in this:
plot->createSimple(ui->grafico,"Graph 1","green");
plot2->createSimple(ui->grafico2,"Graph 2","blue");
plot3->createSimple(ui->grafico3,"Graph 3","red");
plot->createSimple(ui->grafico,"Graph 1","green");
plot2->createSimple(ui->grafico2,"Graph 2","blue");
plot3->createSimple(ui->grafico3,"Graph 3","red");
To copy to clipboard, switch view to plain text mode
In this situation, I create the graphs from the "graf" class usign the function "createSimple", pointing each of the graphs to a specific QWidget, giving it a name and setting the color of line. Just to make things even more simple, here is the function createSimple as it is today:
{
gra->setParent(a); //Liga o grafico à widget
//Dimensões do gráfico dentro do widget
gra->setGeometry(0,0,1020,200);
gra
->setAxisScale
(QwtPlot::yLeft,
0,
300);
gra
->setAxisScale
(QwtPlot::xBottom,
0.0,
150);
//plot->setAxisTitle(QwtPlot::xBottom, "Tempo [s]"); //Falta espaço. Tentar colocar na borda do eixo, não embaixo
//plot->setAxisScale(QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue()); //faz a mudança dos números no eixo X
//plot->axisAutoScale(1);
//plot->axisAutoScale(1);
//Coloca grid
grid
->setPen
(QPen(Qt
::gray,
0.0, Qt
::DotLine));
grid->enableX(true);
grid->enableXMin(true);
grid->enableY(true);
grid->enableYMin(false);
grid->attach(gra);
gra->show();
linha->attach(gra);
}
void graf::createSimple(QWidget *a, QString b, QString c)
{
gra = new QwtPlot(QwtText(b));
gra->setParent(a); //Liga o grafico à widget
//Dimensões do gráfico dentro do widget
gra->setGeometry(0,0,1020,200);
gra->setAxisScale(QwtPlot::yLeft,0,300);
gra->setAxisScale(QwtPlot::xBottom,0.0,150);
//plot->setAxisTitle(QwtPlot::xBottom, "Tempo [s]"); //Falta espaço. Tentar colocar na borda do eixo, não embaixo
//plot->setAxisScale(QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue()); //faz a mudança dos números no eixo X
//plot->axisAutoScale(1);
//plot->axisAutoScale(1);
//Coloca grid
grid = new QwtPlotGrid();
grid->setPen(QPen(Qt::gray, 0.0, Qt::DotLine));
grid->enableX(true);
grid->enableXMin(true);
grid->enableY(true);
grid->enableYMin(false);
grid->attach(gra);
gra->show();
linha = new QwtPlotCurve("ECG");
linha->setStyle(QwtPlotCurve::Lines);
linha->setPen(QPen(c));
linha->attach(gra);
}
To copy to clipboard, switch view to plain text mode
But here is where the problem begins, and they are two problems.
First, I simply can't understand why I can't instantiate (I hope this is the technical word for that) the variables "gra", "linha" [the line] and "grid"
QwtPlot *gra;
QwtPlotGrid *grid;
QwtPlotCurve *linha;
To copy to clipboard, switch view to plain text mode
in the "graf.h" file; I have to instantiate them always in the "graph.cpp" file, which is not the correct way of doing it and, btw, its probably the source of all of my problems. If I try to instantiate the variables in the "graf.h" file, the compilation runs O.K., but when I start the program as soon as I click in the Start button to make the graphs appear, the software crash and it don't say what happened. So in order to make my software works to this point, I have always to instantiate in the .cpp file, what is wrong.
So, my first question: is there a official problem about instantiating Qwt variables in the .h file? Why can't and do that in my software?
---
Second and most annoying problem: once instantiating the variables in the .cpp file, I simply can't make the lines fit in the correct graph. Rather, they insist always to appear in the last graph in the window. Let me explain.
Here is the code I use to "translate" the string of data from the socket client to Y variables to each of the Qwt graph in the version that works fine:
.h file:
public:
std::vector<double> xs1;
std::vector<double> ys1;
std::vector<double> xs2;
std::vector<double> ys2;
std::vector<double> xs3;
std::vector<double> ys3;
double cur_x1, cur_x2, cur_x3;
int str1X, str2X, str3X;
public:
std::vector<double> xs1;
std::vector<double> ys1;
std::vector<double> xs2;
std::vector<double> ys2;
std::vector<double> xs3;
std::vector<double> ys3;
double cur_x1, cur_x2, cur_x3;
QString str1, str2, str3;
int str1X, str2X, str3X;
To copy to clipboard, switch view to plain text mode
.cpp file:
leitura
= QString(socket
->readLine
());
str1 = leitura.section(' ',0,0);
str1X = str1.toInt(NULL);
qDebug() << "1 col:" << str1X << endl;
str2 = leitura.section(' ',1,1);
str2X = str2.toInt(NULL);
qDebug() << "2 col:" << str2X << endl;
str3 = leitura.section(' ',2,2);
str3X = str3.toInt(NULL);
qDebug() << "3 col:" << str3X << endl;
ys1.push_back(str1.toDouble(NULL));
xs1.push_back(cur_x1++);
pmw->curva->setData(&xs1[0],&ys1[0],xs1.size());
pmw->plot->replot();
ys2.push_back(str2.toDouble(NULL));
xs2.push_back(cur_x2++);
pmw->curva2->setData(&xs2[0],&ys2[0],xs2.size());
pmw->plot2->replot();
ys3.push_back(str3.toDouble(NULL));
xs3.push_back(cur_x3++);
pmw->curva3->setData(&xs3[0],&ys3[0],xs3.size());
pmw->plot3->replot();
leitura = QString(socket->readLine());
str1 = leitura.section(' ',0,0);
str1X = str1.toInt(NULL);
qDebug() << "1 col:" << str1X << endl;
str2 = leitura.section(' ',1,1);
str2X = str2.toInt(NULL);
qDebug() << "2 col:" << str2X << endl;
str3 = leitura.section(' ',2,2);
str3X = str3.toInt(NULL);
qDebug() << "3 col:" << str3X << endl;
ys1.push_back(str1.toDouble(NULL));
xs1.push_back(cur_x1++);
pmw->curva->setData(&xs1[0],&ys1[0],xs1.size());
pmw->plot->replot();
ys2.push_back(str2.toDouble(NULL));
xs2.push_back(cur_x2++);
pmw->curva2->setData(&xs2[0],&ys2[0],xs2.size());
pmw->plot2->replot();
ys3.push_back(str3.toDouble(NULL));
xs3.push_back(cur_x3++);
pmw->curva3->setData(&xs3[0],&ys3[0],xs3.size());
pmw->plot3->replot();
To copy to clipboard, switch view to plain text mode
So let me explain: "leitura" reads the entire line that the socket client receives, and str1, str2 and str3 receives the three columns of data from "leitura", each of them with the Y coordinates for each of the graphs. Later each of the "ys" receives the data from "str1, str2 and str3" converted to double. Finally, a MainWindow vector called "*pmw" acess the varibles "curva" and "plot" from MainWindow (see first code) and ask them to execute the functions "setData()" and "replot()".
As I sad earlier, this code is fine. The problem is when I try to execute a similar version using OO for the Qwt plot.
Theorically, everything that I should do of different, if the variables "gra" and "linha" were instantiated in the "graf.h", would be to change the pmw path to something like this:
pmw->plot->linha->setData(&xs1[0],&ys1[0],xs1.size());
pmw->plot->replot();
pmw->plot2->linha->setData(&xs2[0],&ys2[0],xs2.size());
pmw->plot2->replot();
pmw->plot3->linha->setData(&xs3[0],&ys3[0],xs3.size());
pmw->plot3->replot();
pmw->plot->linha->setData(&xs1[0],&ys1[0],xs1.size());
pmw->plot->replot();
pmw->plot2->linha->setData(&xs2[0],&ys2[0],xs2.size());
pmw->plot2->replot();
pmw->plot3->linha->setData(&xs3[0],&ys3[0],xs3.size());
pmw->plot3->replot();
To copy to clipboard, switch view to plain text mode
[continue in the next post]
[continuing]
But if the variables are not instantiated in the "graf.h", they are not found by the "pmw" and this code is found useless. What I tried to do, than, was to create functions in "graph.cpp" that were capable of changing the value of this variables despite they were instantiated in the .cpp file (see first problem). But always when I try to do so, the software confuses itself and begin to plot only the last of the graphs that was instantiated.
So for example, if the code is put entirely as it should, instead each of the graphs receives each of the data and show the curve, only the third graph plots the curve receiving its values. The other two remain "silent". Now if I create only two graphs in the MainWindow.cpp:
plot->createSimple(ui->grafico,"Graph 1","green");
plot2->createSimple(ui->grafico2,"Graph 2","blue");
//plot3->createSimple(ui->grafico3,"Graph 3","red");
plot->createSimple(ui->grafico,"Graph 1","green");
plot2->createSimple(ui->grafico2,"Graph 2","blue");
//plot3->createSimple(ui->grafico3,"Graph 3","red");
To copy to clipboard, switch view to plain text mode
but I lat the code for reading the column the same (including the changes to plot3, that was not instantiaded), than the graph3 do'nt appear in the software, the graph1 doesn't show anything and the graph2 plots the data from graph3!!
And so on, doesn't matter how many different functions I use to call setData(), it will always plot only the last graph while the others will remain clear.
Do anybody know how to solve my 2 problems? Probably by solving the first one the second goes away too.
Sorry for the immense post, but I think it was necessary to explain my problem exactly. I spend more than 6 hours by now trying to solve it and I'm beginning to become borrowed :P
Thanks for your time! =]
Bookmarks