Frage zu Qwt

Dein Thema passt einfach in kein Forum? Dann probiers mal hier.
Antworten
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Frage zu Qwt

Beitrag von pfid »

Ich bin dabei, ein kleines Statistik-Tool zu programmieren. Ich möchte dabei im Programm auch einfache Diagramme darstellen (Wert pro Zeit, 1-n Kurven pro Diagramm). Natürlich fiel mir dafür als erstes Qwt ein, was selbiges wohl ausreichend beherrscht.

Was ich jedoch auch brauche, ist der Export von Diagrammen in ein webtaugliches Format - vorzugsweise PNG. Per google hab ich rausgefunden, dass man Qwt Diagramme zumindest ins SVG Format exportieren kann.
Wie siehts mit PNG aus? Traumhaft wäre noch, wenn man einzelne Kurven als einzelne, transparente PNGs exportieren könnte, so dass ich diese im HTML übereinander legen kann und bei Klick ein/ausblenden kann.

Ist sowas mit Qwt denkbar, oder, falls nein, kennt jemand eine alternative Library mit der ich so etwas umsetzen könnte? (graphviz..?) Selbige sollte unter windows, linux und mac verfügbar sein.

Frage 2:
Zusätzlich zu normalen Kurven im X/Y Diagramm bräuchte ich noch Markierungen. Zum einen senkrechte Striche, die ein bestimmtes Ereignis kennzeichnen, sowie einen farblich(hintergrund) markierten Bereich im Diagramm, der einen besonderen Zeitraum kennzeichnet.
Das sollte mit Qwt möglich sein, oder?
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

kennt jemand eine alternative Library mit der ich so etwas umsetzen könnte?
Ja die nennt sich "Qt" :wink:

In Qt kannst du ja jedes beliebige Widget in ein von Qt unterstütztes Graphikformat (u.a. auch png) exportieren (s. http://doc.trolltech.com/4.5/qpixmap.html#grabWidget). Daher hast du also folgende Möglichkeiten:

* du erstellst mit Qwt ein Diagramm, welches genau deinen Wünschen entsprechend aussieht (z.B. ohne Achsen, Hintergrundfarbe usw.) und erstellst daraus via QPixmap direkt eine PNG
* du erstellst die Graphik gleich selbst (QPainter auf QPixmap, siehe http://www.qtforum.de/forum/viewtopic.php?t=8826)

bräuchte ich noch Markierungen. Zum einen senkrechte Striche, die ein bestimmtes Ereignis kennzeichnen, sowie einen farblich(hintergrund) markierten Bereich im Diagramm, der einen besonderen Zeitraum kennzeichnet.
Also http://qwt.sourceforge.net/plot.png zeigt ja solche "Cursors" (senkrechte Linien). Ich habe gerade keine Qwt-Installation, aber findest du dies nicht in den Beispielen? Ob sich die Hintergrundfarbe zwischen zwei Cursors auch verstellen lässt, weiss ich nicht.

hth..
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Das Diagramm direkt mit Qt zu zeichnen, hatte ich mir auch schon überlegt. Habe in diese Richtung allerdings noch nie was mit Qt gemacht, und weiß nicht wie (un-?)komfortabel das Zeichen mit immer unterschiedlicher Achsenskalierung in Qt ist.

Dass ich die Qwt Diagramme direkt mit Qt exportieren kann, wusste ich nicht, und erleichtert die Sache wohl erheblich, ich denke so werd ichs probieren :)
Uwe
Beiträge: 176
Registriert: 9. Oktober 2005 13:37
Wohnort: München

Beitrag von Uwe »

a)
Mit Qt Bordmitteln kannst Du einen Screenshot von Deinem Plot Widget erzeugen - das mag für viele Zwecke genügen. Besser ist es aber Dein Diagramm mit QwtPlot::print auf ein QImage rendern. Das Image kannst Du dann als PNG ( oder jedes andere Raster Bildformat ) speichern.

z.B:

QImage image(1000, 1000, ...);
image.fill(Qt::transparent);
plot->print(image, ...);
image.save(...);

b)
Markierungen nennen sich in Qwt "überrachenderweise" Marker (QwtPlotMarker). Das bode Beispiel zeigt Marker in Form von vertikalen Linien.

c)
Um Intervalle durch einen farbigen Hintergrund darzustellen würde ich ein eigenes Plot Item implementieren. Schau Dir mal das cpuplot Beispiel an. Da ist so ein Background Item implementiert.

HTH,
Uwe
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Grml, eben nen langen Text getippt, und dann aus versehen gelöscht.

Kurzfassung: Habe Probleme, Flächen im Diagramm zu markieren

Ansatz: eigenes Plotitem dass ein Rechteck zeichnet. Dem Plotitem wird die Start-Sekunde im Diagramm sowie die End-Sekunde mitgegeben, dazwischen soll auf der ganzen Höhe das Diagramms ein farbiges Rechteck gemalt werden.

Position/Breite des Rechtecks stimmt, nur die Höhe macht er mir immer auf 4 Pixel, und ich weiß nicht warum.

[edit] Hab alle Probleme nun gelöst, das Widget funktioniert wies soll. Der Übersichtlichkeit wegen habe ich den alten Text entfernt und den fertigen Code gepostet, falls jemand ein solches Widget mal brauchen könnte:

Header:

Code: Alles auswählen

//******************************************************
// class AreaMarker
//******************************************************

class AreaMarker: public QwtPlotItem
{
   public:

      AreaMarker(const QString& title, const QColor& color, int startSec, int endSec);

      virtual int rtti() const { return QwtPlotItem::Rtti_PlotUserItem; }

      void updateLegend(QwtLegend *legend) const;

      virtual void draw(QPainter* p, const QwtScaleMap& xMap,
                        const QwtScaleMap& yMap, const QRect& rect) const;

      // get

      int getStart() { return startSec; }
      int getEnd() { return endSec; }

      // set

      int setStart(int to) { startSec = to ; return 0; }
      int setEnd(int to) { endSec = to; return 0; }

   private:

      QColor color;
      int startSec;
      int endSec;
};
Impl:

Code: Alles auswählen

//******************************************************
// class AreaMarker
//******************************************************
// ctor
//******************************************************

AreaMarker::AreaMarker(const QString& title, const QColor& color, int startSec, int endSec)
      : QwtPlotItem(title), color(color), startSec(startSec), endSec(endSec)
{
   startSec = endSec = 0;
   setItemAttribute(Legend, true);
}

//******************************************************
// draw
//******************************************************

void AreaMarker::draw(QPainter* p, const QwtScaleMap& xMap,
                        const QwtScaleMap& /*yMap*/, const QRect& rect) const
{
   QRect areaRect;
   areaRect.setX(xMap.transform(startSec));
   areaRect.setY(rect.y());
   areaRect.setHeight(rect.height());
   areaRect.setWidth(xMap.transform(endSec) - xMap.transform(startSec));

   p->save();
   p->setBrush(QBrush(color, Qt::SolidPattern));
   p->setOpacity(0.3);
   p->setPen(QPen(Qt::NoPen));
   p->drawRect(areaRect);
   p->restore();
}

//******************************************************
// update legend
//******************************************************

void AreaMarker::updateLegend(QwtLegend *legend) const
{
   if ( !legend )
      return;

   QwtPlotItem::updateLegend(legend);

   QWidget *widget = legend->find(this);

   if ( !widget || !widget->inherits("QwtLegendItem") )
      return;

   QwtLegendItem *legendItem = (QwtLegendItem *)widget;

#if QT_VERSION < 0x040000
   const bool doUpdate = legendItem->isUpdatesEnabled();
   #else
   const bool doUpdate = legendItem->updatesEnabled();
#endif

   legendItem->setUpdatesEnabled(false);

   const int policy = legend->displayPolicy();

   if (policy == QwtLegend::FixedIdentifier)
   {
      int mode = legend->identifierMode();

      if (mode & QwtLegendItem::ShowLine)
         legendItem->setCurvePen(QPen(color));

      if (mode & QwtLegendItem::ShowText)
         legendItem->setText(title());
      else
         legendItem->setText(QwtText());

      legendItem->setIdentifierMode(mode);
   }
   else if (policy == QwtLegend::AutoIdentifier)
   {
      int mode = 0;

      legendItem->setCurvePen(QPen(color));
      mode |= QwtLegendItem::ShowLine;

      if (!title().isEmpty())
      {
         legendItem->setText(title());
         mode |= QwtLegendItem::ShowText;
      }
      else
      {
         legendItem->setText(QwtText());
      }

      legendItem->setIdentifierMode(mode);
   }

   legendItem->setUpdatesEnabled(doUpdate);
   legendItem->update();
}
updateLegend() ist copy & paste von QPlotCurve. Da ich für meinen Fall weder Symbol noch Linestyle konfigurieren muss, gibts dafür keine Optionen. Einfach in qwt_plot_curve.cpp nachschauen, dort ist Symbol & Linestyle implementiert.
Antworten