Ich habe echt ein mieses Problem und hoffe, dass ihr mir helfen könntet... aaaalso;-)
Ich habe in mein aktuelles Qt-Projekts ein QwtPlot mit QwtPlotCurve eingebunden (Beide Klassen natürlich überschrieben). Ich steuer mit meinem Programm Geräte an, die Messdaten zurückgeben. Es sind drei verschiedene Messwerte pro Gerät. 8 Geräte sind angeschlossen. Pro Messwert wird in einer PlotCurve ein Datensatz aus Messwert und Zeitstempel angefügt. Also es kommen schon einige Datensätze zusammen. Nun habe ich ein Problem, dass mein Programm immer nach 6 bis 7 Stunden abschmiert! Es kommt das übliche Visual-C++ Fenster mit dem Runtime-Error. Anschließend schaue ich in den Debugteil im Creator und es ist folgendes zu sehen:
Code: Alles auswählen
Warning: QPainter::end: Painter ended with 3 saved states
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_allocMeasurementdata.h
Code: Alles auswählen
#ifndef MEASUREMENTDATA_H
#define MEASUREMENTDATA_H
#include "eurotherm.h"
#include "eurothermexception.h"
#include "myqwtplotcurve.h"
#include <qwt_plot.h>
#include <qwt_legend.h>
#include <QList>
#include <QTime>
#include <QDateTime>
#include <QFile>
#include <QDir>
#define DELIMITER QChar((int) 9)
class MeasurementData : public QwtPlot
{
public:
MeasurementData(QWidget *parent);
void init(); // initialisiert den Plot (Kurven, Legende, ...)
void setEurothermList(QList<Eurotherm*> tEuroList); // übergibt die Liste aller Eurotherms
void startMeasurement(); // startet die Messung
QString measure(); // fragt die Messwerte ab und stellt sie dar
void stopMeasurement(); // stoppt die Messung
void initTempFile(); // temporär gespeicherte Datei initialisieren
void saveTempData(); // speichert Daten in TempDatei
bool saveMeasurement(QString &fileName); // speichert alle Messwerte als CSV-Datei
void hideCurve(QwtPlotItem *tPlotItem); // blendet eine Kurve aus
void showCurve(QwtPlotItem *tPlotItem); // blendet eine Kurve ein
void hideAout(bool); // blendet die Kurve Aout aus (true) bzw ein (false)
void hideWsp(bool); // blendet die Kurve Wsp aus (true) bzw ein (false)
void hidePv(bool); // blendet die Kurve Pv aus (true) bzw ein (false)
private:
QList<Eurotherm*> euroList;
QList<MyQwtPlotCurve*> wspList;
QList<MyQwtPlotCurve*> aoutList;
QList<MyQwtPlotCurve*> pvList;
QTime measurementTime;
QList<QPen> penList; // Liste mit verschiedenen Farben
int latestSample; // merkt sich die Anzahl der gespeicherten Datensätze
QFile *tempFile;
int savesCount; // merkt sich die Anzahl der Speichervorgänge
bool isRunning; // true, wenn Messung gestartet wurde
};
#endif // MEASUREMENTDATA_H
Code: Alles auswählen
#include "measurementdata.h"
#include <QLabel>
MeasurementData::MeasurementData(QWidget *parent) :
euroList(),
wspList(),
aoutList(),
pvList(),
measurementTime(0,0,0),
penList(),
latestSample(0),
tempFile(new QFile()),
savesCount(1),
isRunning(false)
{
penList.append(QPen(Qt::red, 3));
penList.append(QPen(Qt::red, 3, Qt::DotLine));
penList.append(QPen(Qt::blue, 3));
penList.append(QPen(Qt::blue, 3, Qt::DotLine));
penList.append(QPen(Qt::yellow, 3));
penList.append(QPen(Qt::yellow, 3, Qt::DotLine));
penList.append(QPen(Qt::black, 3));
penList.append(QPen(Qt::black, 3, Qt::DotLine));
penList.append(QPen(Qt::green, 3));
penList.append(QPen(Qt::green, 3, Qt::DotLine));
penList.append(QPen(Qt::magenta, 3));
penList.append(QPen(Qt::magenta, 3, Qt::DotLine));
penList.append(QPen(Qt::white, 3));
penList.append(QPen(Qt::white, 3, Qt::DotLine));
penList.append(QPen(Qt::darkGray, 3));
penList.append(QPen(Qt::darkGray, 3, Qt::DotLine));
}
// initialisiert den this (Kurven, Legende, ...)
void MeasurementData::init()
{
wspList.clear();
aoutList.clear();
pvList.clear();
this->clear();
this->initTempFile();
this->setTitle("Messung");
this->insertLegend(new QwtLegend());
this->legend()->setItemMode(QwtLegend::CheckableItem);
this->setAxisTitle(xBottom, "t in sec");
this->setAxisTitle(yLeft, "WSP");
QString name;
// für jeden Eurotherm eine Kurve erstellen
for(int i=0; i<euroList.size(); i++)
{
name.clear();
name.append(euroList.at(i)->getAssay());
name.append("-");
name.append(euroList.at(i)->getType());
// Kurve erstellt und zur Liste hinzugefügt
wspList.append(new MyQwtPlotCurve(name));
aoutList.append(new MyQwtPlotCurve(name));
pvList.append(new MyQwtPlotCurve(name));
wspList.at(i)->attach(this);
wspList.at(i)->setPen(penList.at(i));
aoutList.at(i)->setPen(penList.at(i));
pvList.at(i)->setPen(penList.at(i));
}
this->replot();
}
// fragt die Messwerte ab und stellt sie dar
QString MeasurementData::measure()
{
QString err = "";
// 4Test start
// for(int i=0; i<euroList.size(); i++)
// {
// pvList.at(i)->deleteAll();
// aoutList.at(i)->deleteAll();
// wspList.at(i)->deleteAll();
// }
// qDebug() << QTime::currentTime().toString("hh:mm::ss");
// Test ende
// falls immer mehr als eine Minute verstrichen ist,
// speichere Daten zwischen
if(this->measurementTime.elapsed() >= (60*1000*savesCount))
this->saveTempData();
float value = -1;
for(int i=0; i< euroList.size(); i++)
{
try{
value = euroList.at(i)->getWSP();
wspList.at(i)->addSample((double) measurementTime.elapsed()/1000, (double) value);
} catch(EurothermException e)
{
// Im Fall eines Fehlers wird eine -1 gespeichert
wspList.at(i)->addSample((double) measurementTime.elapsed()/1000, (double) -1);
err = e.getErrorString();
err.append("\n");
}
try{
value = euroList.at(i)->getAout();
aoutList.at(i)->addSample((double) measurementTime.elapsed()/1000, (double) value);
} catch(EurothermException e)
{
// Im Fall eines Fehlers wird eine -1 gespeichert
aoutList.at(i)->addSample((double) measurementTime.elapsed()/1000, (double) -1);
err.append(e.getErrorString());
err.append("\n");
}
try{
value = euroList.at(i)->getPV();
pvList.at(i)->addSample((double) measurementTime.elapsed()/1000, (double) value);
} catch(EurothermException e)
{
// Im Fall eines Fehlers wird eine -1 gespeichert
pvList.at(i)->addSample((double) measurementTime.elapsed()/1000, (double) -1);
err.append(e.getErrorString());
err.append("\n");
}
}
this->replot();
return err;
}
// übergibt die Liste aller Eurotherms
void MeasurementData::setEurothermList(QList<Eurotherm*> tEuroList)
{
this->euroList.clear();
this->euroList = tEuroList;
this->init();
}
// startet die Messung
void MeasurementData::startMeasurement()
{
if(!isRunning)
{
this->measurementTime.restart();
isRunning = true;
}
}
// stoppt die Messung
void MeasurementData::stopMeasurement()
{
this->isRunning = false;
}
// temporär gespeicherte Datei initialisieren
void MeasurementData::initTempFile()
{
delete tempFile;
QDir dir;
// Falls der Ordner "Messwerte" nicht existiert, soll er erstellt werden
if(!dir.exists("Messwerte"))
{
dir.mkdir("Messwerte");
}
QString row, tString;
QByteArray tArray;
tempFile = new QFile("Messwerte/" + QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss")+".csv~");
tempFile->open(QFile::WriteOnly | QFile::Text);
// Header zusammenbauen
row.append(tr("########## start Header ##########") + tr("\n") +
tr("# In-situ PVD Templog v1") + tr("\n") +
tr("# Date") + DELIMITER + QDate::currentDate().toString("yyyy/MM/dd") + tr("\n") +
tr("# Time") + DELIMITER + QTime::currentTime().toString("hh:mm:ss.ms") + tr("\n") +
tr("########## end Header ##########") + tr("\n\n"));
row.append(tr("Uhrzeit") +
DELIMITER +
tr("Zeit in sec") +
DELIMITER);
// erste Zeile zusammenbauen
for(int i=0;i<euroList.size();i++)
{
// Zeit;CU-HL;CU-EC; ...
tString.append(DELIMITER +
euroList.at(i)->getAssay() +
tr("-") +
euroList.at(i)->getType() +
DELIMITER +
tr(" ") +
DELIMITER);
row.append(tString);
tString.clear();
}
// Zeilenumbruch
row.append(tr("\n")+
DELIMITER);
for(int i=0;i<euroList.size();i++)
row.append(DELIMITER +
tr("WSP") +
DELIMITER +
tr("Aout") +
DELIMITER +
tr("PV"));
// Zeilenumbruch
row.append("\n");
tArray.append(row);
tempFile->write(tArray.data());
tempFile->close();
}
// speichert Daten in TempDatei
void MeasurementData::saveTempData()
{
QString row;
QByteArray tArray;
this->savesCount++;
tempFile->open(QFile::Append | QFile::Text);
for(;latestSample<wspList.at(0)->getSampleCount();latestSample++)
{
// Uhrzeit
row.append(wspList.at(0)->getTime(latestSample) +
DELIMITER);
// Zeit
row.append(QString::number(wspList.at(0)->x(latestSample)) +
DELIMITER);
for(int i=0;i<wspList.size();i++)
{
// Messwerte einer Zeile
row.append(QString::number(wspList.at(i)->y(latestSample))+
DELIMITER);
// Messwerte einer Zeile
row.append(QString::number(aoutList.at(i)->y(latestSample)) +
DELIMITER);
// Messwerte einer Zeile
row.append(QString::number(pvList.at(i)->y(latestSample)) +
DELIMITER);
}
// Zeilenumbruch
row.append("\n");
tArray.append(row);
tempFile->write(tArray.data());
tArray.clear();
row.clear();
}
tempFile->close();
}
// speichert alle Messwerte als CSV-Datei
bool MeasurementData::saveMeasurement(QString &fileName)
{
this->saveTempData();
// Überschreiben, falls Datei schon vorhanden
if(QFile::exists(fileName))
QFile::remove(fileName);
return this->tempFile->copy(fileName);
}
// blendet eine Kurve aus
void MeasurementData::hideCurve(QwtPlotItem *tPlotItem)
{
tPlotItem->hide();
}
// blendet eine Kurve ein
void MeasurementData::showCurve(QwtPlotItem *tPlotItem)
{
tPlotItem->show();
}
// blendet die Kurve Aout aus (true) bzw ein (false)
void MeasurementData::hideAout(bool checked)
{
if(!checked)
{
foreach(MyQwtPlotCurve *my, aoutList)
my->detach();
} else
{
foreach(MyQwtPlotCurve *my, aoutList)
{
my->attach(this);
my->show();
}
this->setAxisTitle(yLeft, "Aout");
}
}
// blendet die Kurve Wsp aus (true) bzw ein (false)
void MeasurementData::hideWsp(bool checked)
{
if(!checked)
{
foreach(MyQwtPlotCurve *my, wspList)
my->detach();
} else
{
foreach(MyQwtPlotCurve *my, wspList)
{
my->attach(this);
my->show();
}
this->setAxisTitle(yLeft, "WSP");
}
}
// blendet die Kurve Pv aus (true) bzw ein (false)
void MeasurementData::hidePv(bool checked)
{
if(!checked)
{
foreach(MyQwtPlotCurve *my, pvList)
my->detach();
} else
{
foreach(MyQwtPlotCurve *my, pvList)
{
my->attach(this);
my->show();
}
this->setAxisTitle(yLeft, "PV");
}
}
Code: Alles auswählen
#ifndef MYQWTPLOTCURVE_H
#define MYQWTPLOTCURVE_H
#include <qwt_plot_curve.h>
#include <QTime>
class MyQwtPlotCurve : public QwtPlotCurve
{
public:
explicit MyQwtPlotCurve(QString &tName);
void addSample(double x, double y); // fügt einen Messwert zur Kurve hinzu
int getSampleCount(); // gibt die Anzahl der Messwerte zurück
inline QString getName() const {return this->name;} // gibt den Namen der Kurve zurück
inline QString getTime(int index) const {return timeList.at(index);} // gibt die Uhrzeit zurück, die an der Stelle index steht
void deleteAll(); // Test
private:
QString name;
QVector<double> v_x;
QVector<double> v_y;
QStringList timeList;
};
#endif // MYQWTPLOTCURVE_H
Code: Alles auswählen
#include "myqwtplotcurve.h"
MyQwtPlotCurve::MyQwtPlotCurve(QString &tName) :
QwtPlotCurve(tName),
v_x(),
v_y(),
timeList()
{
this->setRenderHint(QwtPlotItem::RenderAntialiased);
}
// fügt einen Messwert zur Kurve hinzu
void MyQwtPlotCurve::addSample(double x, double y)
{
this->timeList.append(QTime::currentTime().toString("hh:mm:ss"));
this->v_x.append(x);
this->v_y.append(y);
this->setData(v_x, v_y);
}
// gibt die Anzahl der Messwerte zurück
int MyQwtPlotCurve::getSampleCount()
{
return this->v_x.size();
}
// TEst
void MyQwtPlotCurve::deleteAll()
{
this->v_x.clear();
this->v_y.clear();
}
Vielen Dank für alles, was weiterhilft!!!