Seite 1 von 2
Qt Live Plot
Verfasst: 5. Dezember 2011 16:13
von surfman19
Hallo,
Ich moechte mit Qt daten plotten. Ich empfange jede Sekunde einen neuen Datenpunkt und moechte den dann ins Liniendiagramm hinzufuegen? Bietet Qt was an oder kann ich etwas fertiges verwenden und erweitern?
LG
Re: Qt Live Plot
Verfasst: 5. Dezember 2011 16:56
von Christian81
Plotting -> qwt
Oder eben was selbst schreiben - allerdings sollte man da schon etwas auf die Performance schauen.
Re: Qt Live Plot
Verfasst: 5. Dezember 2011 17:52
von surfman19
ok ich versuche es!
kansnt du mir sagen was hier falsch ist?
Code: Alles auswählen
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
mainwindow.cpp(6): error C2512: 'Ui::MainWindow' : no appropriate default constructor available
bezieht sich auf hier:
ui(new Ui::MainWindow)
Re: Qt Live Plot
Verfasst: 5. Dezember 2011 18:31
von franzf
Der gepostete Teil ist OK. Hast du evtl selber in ui_mainwindow.h rumeditiert (z.B. Selber nen Konstruktor eingefügt)?
Re: Qt Live Plot
Verfasst: 5. Dezember 2011 19:38
von surfman19
die klasse die der moc in der ui_mainwindow.h erzeugt:
class Ui_MainWindowClass

Re: Qt Live Plot
Verfasst: 6. Dezember 2011 00:36
von surfman19
Hi,
wie kann ich die groesse des QwtPlot dynamisch skalieren so wie den pushbutton? das QwtPlot hat im moment immer eine fixe groesse ;(
Der Frame welches QwtPlot verwendet ist doch im GridLayout...hm
Code: Alles auswählen
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created: Sun 4. Dec 18:19:38 2011
** by: Qt User Interface Compiler version 4.7.4
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QFrame>
#include <QtGui/QGridLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QMainWindow>
#include <QtGui/QMenuBar>
#include <QtGui/QPushButton>
#include <QtGui/QStatusBar>
#include <QtGui/QToolBar>
#include <QtGui/QWidget>
#include <qwt_plot.h>
#include <qwt_plot_curve.h>
QT_BEGIN_NAMESPACE
class Ui_MainWindowClass
{
public:
QWidget *centralWidget;
QGridLayout *gridLayout;
QFrame *frame;
QPushButton *pushButton;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
QwtPlot *qwtPlot;
void setupUi(QMainWindow *MainWindowClass)
{
if (MainWindowClass->objectName().isEmpty())
MainWindowClass->setObjectName(QString::fromUtf8("MainWindowClass"));
MainWindowClass->resize(474, 407);
centralWidget = new QWidget(MainWindowClass);
centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
gridLayout = new QGridLayout(centralWidget);
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(11, 11, 11, 11);
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
frame = new QFrame(centralWidget);
frame->setObjectName(QString::fromUtf8("frame"));
frame->setFrameShape(QFrame::StyledPanel);
frame->setFrameShadow(QFrame::Raised);
gridLayout->addWidget(frame, 0, 0, 1, 1);
qwtPlot = new QwtPlot(frame);
pushButton = new QPushButton(centralWidget);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
gridLayout->addWidget(pushButton, 1, 0, 1, 1);
MainWindowClass->setCentralWidget(centralWidget);
menuBar = new QMenuBar(MainWindowClass);
menuBar->setObjectName(QString::fromUtf8("menuBar"));
menuBar->setGeometry(QRect(0, 0, 474, 21));
MainWindowClass->setMenuBar(menuBar);
mainToolBar = new QToolBar(MainWindowClass);
mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
MainWindowClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(MainWindowClass);
statusBar->setObjectName(QString::fromUtf8("statusBar"));
MainWindowClass->setStatusBar(statusBar);
retranslateUi(MainWindowClass);
QMetaObject::connectSlotsByName(MainWindowClass);
} // setupUi
void retranslateUi(QMainWindow *MainWindowClass)
{
MainWindowClass->setWindowTitle(QApplication::translate("MainWindowClass", "MainWindow", 0, QApplication::UnicodeUTF8));
pushButton->setText(QApplication::translate("MainWindowClass", "PushButton", 0, QApplication::UnicodeUTF8));
} // retranslateUi
};
namespace Ui {
class MainWindowClass: public Ui_MainWindowClass {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAINWINDOW_H
Re: Qt Live Plot
Verfasst: 6. Dezember 2011 07:41
von franzf
Lies dir bitte mal durch, was in dem ui_mainwindow.h ganz oben steht...
Dass dein label im gridLayout liegt ist ja schön, aber das gridLayout kontrolliert nur die Widgets, die direkt drinnen liegen - children von diesen Widgets fasst es nicht an!

st nicht nur bei QGridLayout so, sondern bei jeder Layoutklasse) Du brauchst also ein weiteres Layout im frame, in das du dann dein plot-widget legst.
Zwei Sachen noch:
Du könntest dir viele deiner Fragen sparen, wenn du einfach mal in Ruhe die Doku lesen würdest. Die ist umfangreich und liefert zu so gut wie allem Beispielanwendungen mit.
Desweiteren sollte in jedem Thread nur ein Thema behandelt werden, sonst wirds langsam unübersichtlich. Hier sei dir verziehen, du hast gemeint das Verhalten liegt an QwtPlot. Bitte aber in Zukunft darauf achten, danke

Re: Qt Live Plot
Verfasst: 6. Dezember 2011 15:45
von surfman19
ok, klappt! thx

Re: Qt Live Plot
Verfasst: 6. Dezember 2011 21:37
von surfman19
Hallo,
bietet das qwt die moeglichkeit immer nur 25 datenpunkte im plot zu haben? es werden laufend neue hinzugefuegt, dh der älteste datenpunkt muesste dann rausfallen...
ich habe im moment ein array erstellt und verwalte darin nur die 25 aktuellsten daten punkte...
habe in der qwt doku nichts gefunden fuer den spezialfall...
LG
Re: Qt Live Plot
Verfasst: 7. Dezember 2011 19:19
von ScyllaIllciz
Die qwt lib kümmert sich nicht um die Daten, sie zeigt nur die Daten an!
Das heißt Du musst Dich selber um Deinen FiFo kümmern!
Re: Qt Live Plot
Verfasst: 7. Dezember 2011 20:56
von surfman19
ok, das problem ist wenn ich immer einen datenpunkt loesche und hinzufuege, dann bleibt das diagramm nicht auf den datenbereich zentriert...dh...machmal ist links zwischen ersten datenpunkt und der y achse ein zwischenraum und manchmal auf der rechten seite...
die x achse (zeit) wird laufend erhoeht, und immer nur 20 punkte dargestellt...
verstehst du?
LG
Re: Qt Live Plot
Verfasst: 7. Dezember 2011 21:12
von ScyllaIllciz
Du musst schon genau sagen, was Du machen willst. Willst Du einen kontinuierlichen Plot mit immer der selben Anzahl an Punkten oder willst Du einen statischen Plot? Oder zeige ein Bild welchen das Problem darstellt oder ein Bild, wie Du es haben willst oder stell ein Beispiel hier rein, mit dem man das Problem nachvollziehen kann.
Re: Qt Live Plot
Verfasst: 7. Dezember 2011 21:25
von surfman19
abstand rechts:
http://img10.imageshack.us/img10/8818/plots.png
abstand links:
http://img710.imageshack.us/img710/9715/plot2n.png
ich will immer die gleiche anzahl an punkten anzeigen....aber mit fortlaufender zeit:
Code: Alles auswählen
curve->setRawSamples(&vec_xval[0], &vec_yval[0], size);
...vec_xval erhoeht laufend
...size bleibt nach 20 werten auf 20
Re: Qt Live Plot
Verfasst: 7. Dezember 2011 21:55
von ScyllaIllciz
Also ein kontinuierlicher Plot mit der selben X-Achsen Auflösung, richtig?
So wie ich das sehe benutz Du std::vector. Damit habe ich sowas schon gemacht. Der Trick dabei ist die X-Achsenskalierung um die Aktualisierungsrate zu verschieben. D.h. wenn du z.B. jede Sekunde einen neuen Wert hast, musst Du X-Achsauflösung um 1s verschieben.
In Code:
Code: Alles auswählen
double dbPlot1_XShiftStart=m_Plot1_samples_x[Plot1_MaxValue-1];
rotate(m_Plot1_samples_x.begin(), m_Plot1_samples_x.begin()+MaxSpsValues, m_Plot1_samples_x.end());
rotate(m_Plot1_samples_1.begin(), m_Plot1_samples_1.begin()+MaxSpsValues, m_Plot1_samples_1.end());
rotate(m_Plot1_samples_2.begin(), m_Plot1_samples_2.begin()+MaxSpsValues, m_Plot1_samples_2.end());
for (int i=0; i<MaxSpsValues; i++){
m_Plot1_samples_1[Plot1_MaxValue-MaxSpsValues+i]=m_listBuffer11.at(i).value.toDouble();
m_Plot1_samples_2[Plot1_MaxValue-MaxSpsValues+i]=m_listBuffer21.at(i).value.toDouble();
m_Plot1_samples_x[Plot1_MaxValue-MaxSpsValues+i]=dbPlot1_XShiftStart+(i+1)*Plot1_TimeStep;
}
m_Plot1_timeOffset+=Plot1_TimeScale;
ui.qwtPlot->setAxisScale(QwtPlot::xBottom, m_Plot1_timeOffset, m_Plot1_timeOffset+Plot1_TimeBase);
m_Plot1_curve_1->setRawSamples(&m_Plot1_samples_x[0], &m_Plot1_samples_1[0], Plot1_MaxValue);
m_Plot1_curve_2->setRawSamples(&m_Plot1_samples_x[0], &m_Plot1_samples_2[0], Plot1_MaxValue);
ui.qwtPlot->replot();
In Worten. Vector wird um die Zeit x rotiert und der letzte/neue Wert bzw. die letzten/neuen Werte werden mit aktuellen Werten überschrieben. Jetzt noch die X-Achsenskalierung verschieben und fertig.
Ich hoffe Du verstehst was ich meine!
Re: Qt Live Plot
Verfasst: 7. Dezember 2011 23:07
von surfman19
ja!
hab das so gemacht...nicht so schoen wie du

ist bei dir size immer gleich gross?
Code: Alles auswählen
int Plot1_TimeScale = 1;
int Plot1_TimeBase = DATA_POINTS-2;
static int Plot1_timeOffset = 0;
if(vec_xval.size() >= DATA_POINTS)
{
vec_xval.erase (vec_xval.begin(), vec_xval.begin()+1);
vec_yval.erase (vec_yval.begin(), vec_yval.begin()+1);
}
vec_xval.push_back(sx);
vec_yval.push_back(yvalue);
if(vec_xval.size() == DATA_POINTS)
{
Plot1_timeOffset += Plot1_TimeScale;
}
ui->qwtPlot->setAxisScale(2, Plot1_timeOffset, Plot1_timeOffset + Plot1_TimeBase);
if(size < DATA_POINTS)
{
size++;
}
curve->setRawSamples(&vec_xval[0], &vec_yval[0], size);
sx++;
curve->setSymbol(new QwtSymbol(QwtSymbol::Cross, Qt::NoBrush,QPen(Qt::black), QSize(5, 5) ) );
curve->setPen(QColor(Qt::darkGreen));
curve->setStyle(QwtPlotCurve::Lines);
curve->attach(ui->qwtPlot);
ui->qwtPlot->replot();