Qwt-Frage

Alles rund um die Programmierung mit Qt
Antworten
Venni
Beiträge: 9
Registriert: 15. Oktober 2007 15:32

Qwt-Frage

Beitrag von Venni »

Hallo!

Nachdem ich mich ein bisschen in Qt4 eingearbeitet habe, möchte ich nun mit Qwt5 einige Daten darstellen. Dabei handelt es sich um bis zu 50 Kurven, die in einem Plot dargestellt werden sollen. Die Daten sind zentral (in einer QList) in einer "projectData"-Klasse (abgeleitet von QObject) gespeichert und jede Sekunde kommt zu jeder Kurve ein neuer Wert hinzu.

Nun habe ich mir mit dem Designer einen Dialog gebastelt (class VisualisationDialog : public QDialog, public Ui_VisualisationDialog) und kann dort auch einen Qwt-Plot (class gpsviewPlotter : public QwtPlot) darstellen. Wenn ich testhalber im Konstruktor von "gpsviewPlotter" Daten "hartkodiere", also

Code: Alles auswählen

    ...

    curve = new QwtPlotCurve( QString("Curve1") );
    curve->setRenderHint(QwtPlotItem::RenderAntialiased);
    curve->setPen(QPen(Qt::yellow));
    curve->setYAxis(QwtPlot::yLeft);
    curve->attach(this);

    double x[5];
    double y[5];

    x[0] = 0.0; y[0] = 0.0;
    x[1] = 10.0; y[1] = 100.0;
    x[2] = 20.0; y[2] = 10.0;
    x[3] = 30.0; y[3] = -10.0;
    x[4] = 40.0; y[4] = 33.0;

    curve->setData( x, y, 5);
//    curve->setData(gpsviewPlotData(x[0], y[0], (size_t) 5));
    replot();

    ...

dann bekomme ich auch einen vernünftigen Plot. Wie aber kann ich (mit Hilfe von QwtData?) am besten die Daten von "projectData" darstellen? Ich habe mir schon eine setCurveData(double x, double y, int Anzahl) -Methode im gpsviewPlotter geschrieben, aber irgendwie funktioniert das nicht (=> Plot leer). Die Beispiele (z.B. "simple_plot") helfen mir irgendwie nicht weiter.

Uwe schreibt:
Qwt speichert keine Daten, sondern zeichnet sie nur. D.h. Du mußt eine eigene Datenhaltung implementieren, in die Du dann die zusätzlichen Punkte einträgst.
Die Verbindung zwischen Deiner Datenhaltung und Qwt funktioniert über ein QwtData Objekt. Du kannst eine der vordefinierten QwtData Klassen verwenden, wenn aber keines passt, leite einfach ein zu Deiner Datenhaltung passendes ab.
Gibt es dafür Beispiele? Mir noch nicht klar, wie man das macht...

Vielen Dank für Eure Hilfe!

Markus
Uwe
Beiträge: 176
Registriert: 9. Oktober 2005 13:37
Wohnort: München

Beitrag von Uwe »

Ich nehme mal an Deine X-Achse ist die Zeit und jedes Element in Deiner QList besteht aus jeweils 50 Einzelwerten, die man über einen Index ansprechen kann. Zusätzlich hast Du den Startzeitpunkt Deiner Messreihe gespeichert.

Dein QwtData Object könnte dann so aussehen:

Code: Alles auswählen

class YourData: public QwtData
{
public:
   YourData(const ProjectData* data, int valueIndex):
       _data(data),
       _valueIndex(valueIndex)
    {
    }

    virtual QwtData *copy() const
    {
        return new YourData(_data, _valueIndex);
    }

    virtual double x(size_t i) const
    {
        return _data->startTime + i; // seconds
    }

    virtual double y(size_t i) const
    {
        return _data->samples[i].value[_valueIndex];
    }

    virtual QwtDoubleRect boundingRect() const
    {
        // Hier sollte möglichst nichts aufwändiges
        // gerechnet werden. Also am besten die
        // maximalen/minimalen y Werte 
        // beim Anhängen neuer Werte aktualisieren
        // und in ProjectData speichern.

        const double x1 = _data->startTime;
        const double x2 = _data->startTime + i;
        const double y1 = ...;
        const doube y2 = ...;
    }
private:
    const ProjectData *_data;
    const int _valueIndex;
};
Abschliessend mußt Du Deine 50 Kurven anlegen und konfigurieren. Jeder Kurve weist Du dann ein eigenes YourData Objekt mit dem passenden Index zu.

Uwe

PS: Da ProjectData bei Dir von QObject abgeleitet ist, kannst Du das durch QPointer<ProjectData> absichern.
Venni
Beiträge: 9
Registriert: 15. Oktober 2007 15:32

Beitrag von Venni »

Hallo Uwe,

vielen Dank für die schnelle Antwort! Leider kriege ich es immer noch nicht hin. Ich bin jetzt etwas zurückgegangen und versuche jetzt mit einer Funktion

Code: Alles auswählen

void gpsviewPlotter::setCurveData(double *x, double *y, int count) {
  curve->setData(x, y, count);
  replot();
}
die Daten einfach als Felder zu übergeben.

Wenn ich diese Funktion vom gpsviewPlotter-Konstruktor aufrufe (also dort vorher einfach zwei Felder x und y der Größe 5 "hartkodiere"), dann klappt alles. Rufe ich diese Funktion von meinem Visualiserungsdialog auf, stürzt mir das Programm mit "Segmentation fault" ab. Was mache ich da falsch?
Uwe
Beiträge: 176
Registriert: 9. Oktober 2005 13:37
Wohnort: München

Beitrag von Uwe »

Venni hat geschrieben:Was mache ich da falsch?
Keine Ahnung - Du schreibst ja nicht was Du machst oder wo Dein Programm sich verabschiedet.
Die Antwort sollte Dir aber der Debugger verraten.

Uwe
Venni
Beiträge: 9
Registriert: 15. Oktober 2007 15:32

Beitrag von Venni »

Das curve->setData macht die Schwierigkeiten. Komischerweise, wenn ich plotter (Instanz von class gpsviewPlotter : public QwtPlot) in meinem Dialog "public" mache, stürzt er nicht mehr ab. Langsam blicke ich nicht mehr durch...

Kann ich Dir nicht Header- und Code-File per Mail zuschicken und Du guckst mal drauf? Das wäre super!!!

Danke, Markus
Antworten