[C/C++] [Hilfe] Graph zeichnen

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von execUTe, 19. Oktober 2011 .

Schlagworte:
Status des Themas:
Es sind keine weiteren Antworten möglich.
  1. 19. Oktober 2011
    [Hilfe] Graph zeichnen

    Hey Leute,
    ich bin gerade mehr oder minder von der Java-Insel rüber zur C++-Insel geschwommen und komme noch nicht so recht klar. Folgendes Problem:

    Ich möchte fortlaufende Int-Werte (werden in einer Endlosschleife generiert) als Graphen darstellen. Ein guter Vergleich wäre die "Windows Task-Manager"-Systemleistung "Verlauf der CPU-Auslastung".

    Ich versuche derzeit das ganze via GDI+ zu realisieren aber irgendwie haut es nicht so hin wie ich will..
     
  2. 19. Oktober 2011
    AW: [Hilfe] Graph zeichnen

    Hallo!

    Willst du denn externe Bibliotheken verwenden oder soll es nur auf jedem Windows ohne Zusatzinstallationen oder aehnlichem laufen? Soll der "Graph" statisch sein oder dynamisch weiter generiert werden? Welches GUI Toolkit verwendest du oder willst du verwenden?

    Falls Bibliotheken kein Problem sind, dann gibt es sehr viele Moeglichkeiten. Ich habe zum Zeichnen von Graphen schon GTK+ benutzt, das sich fuer Zeichnen allgemein gut eignet, da das Toolkit fuer GIMP entwickelt wurde. Fuer C++ gibt es sogar das GTKmm Interface, wobei du dich wohl mit etwas GDK rumschlagen werden musst.
    Ansonsten ist QT (QPainter) eine gute Alternative oder, falls mehr Funktionalitaet erwuenscht ist, die Erweiterung qwt.
    Wenn das ganze dynamisch sein soll, waere vielleicht sogar eine Benutzung von einer OpenGL/DirectX-Area denkbar.

    Mfg,

    Kolazomai
     
  3. 19. Oktober 2011
    AW: [Hilfe] Graph zeichnen

    Moin und danke für die schnelle Antwort.

    Das ganze sollte ohne externe Bibliotheken und im bestmöglichem Fall plattformübergreifend laufen. Ist es möglich soetwas zu realisieren?

    Der Graph an sich sollte dynamisch sein. Statisch macht in diesem Fall ja keinen Sinn, da die Graph anzeige fortlaufend sein soll.

    Ich habe noch etwas weiter gesucht und habe mich jetzt für QWT (QT SDK) entschieden, da das ja doch ne Menge Funktionalität liefert. Dennoch steh ich gerade mehr oder minder auf dem Schlauch wie ich das ganze realisieren soll.

    Jemand Ahnung von QT oder ne Alternative + Lösungsansatz parat?
     
  4. 19. Oktober 2011
    AW: [Hilfe] Graph zeichnen

    Welche IDE und/oder Compiler, unter welcher Plattform, benutzt du?

    Qt in Verbindung mit Visual Studio 2008 ist genial. Für diesen gibt es einen Qt-Plugin welcher einen Projektwizard und einen GUI-Editor zur Verfügung stellt.

    Um den deinen Graph zu zeichnen kannst du entweder mit den Qt-Schnittstellen (Graphics View Framework) selber machen oder Fertige Klassen benutzten (z.B Qwt).

    // Edit: Ups, letzteres wurde ja schon genannt.
    Na wo liegt den dein genaueres Problem? Fenster erstellen? Widgets platzieren? Auf dem Graphen zeichnen btw. die Benutzung der Qwt Klassen?

    Mfg Rushh0ur
     
  5. 19. Oktober 2011
    AW: [Hilfe] Graph zeichnen

    Ich hatte QT in Verbindung mit Visual Studio 2010 benutzt. Ich mach mich gleich mal auf die Suche nach einem QT-Plugin für 2010.

    Jetzt gerade benutze ich den QT-Creator, welcher meiner Meinung nach ne Menge Fragen aufwirft, wenn man gerade mit C++ anfängt. Habe wie gesagt bisher nur Java kennen gelernt.

    Ist ein dynamischer Graph überhaupt realisierbar nur mit Qwt? Oder brauche ich dazu schon OpenGL / ActiveX?

    Wie kann ich andere include-Pfade angeben? Ich habe ne mysql.h auf die ich zugreifen muss. Oder kann QWT auch anders auf SQL-Datenbanken zugreifen?



    Hier nochmal meine detailierte Problembeschreibung:
    Ich habe eine SQL-Datenbank in die fortlaufend Int-Werte (CPU Usage) geschrieben wird. Diese Daten möchte ich auslesen und als Graph ausgeben. Ich kann mir nicht vorstellen, dass das so schwer zu realisieren ist und dennoch laufe ich permanent gegen die Wand
     
  6. 19. Oktober 2011
    AW: [Hilfe] Graph zeichnen

    Genauer heißt es nicht Plugin sondern Add-In und zu finden hier:
    http://qt.nokia.com/downloads/visual-studio-add-in
    (Keine Ahnung ob es schon mit VS2010 funktioniert)

    Um Qwt zu benutzen musst du zuerst den Sourcecode runter laden und compilieren, dazu einfach im src-Ordner die *.pro öffnen und die Bibliothek erstellen.
    Hast du dies getan findest du im lib Ordner die dazugehörigen Bibliothek.

    Nun kannst du die Bibliothek verwenden, dazu würde ich dir empfehlen die Beispielprojekte im examples-Ordner anzuschauen.

    Wie du include-Pfäde beim Qt-Creator angeben kannst kann ich dir leider nicht sagen, da ich diesen nicht verwende.

    Du kannst jedoch mit Qt auch auf SQL-Datenbanken zugreifen zb. mit dem QSqlDatabase-Objekt. (Beispiele zur Verwendung sind in der Qt-Hilfe mehr als genug dabei und relativ intuitiv)

    PS: Im Qwt-examples-Ordner ist sogar ein direktes Beispiel dabei wie man die CPU-Usage auslesen und in Echtzeit plotten kann.

    Mfg Rushh0ur
     
  7. 19. Oktober 2011
    AW: [Hilfe] Graph zeichnen

    Okay danke ich werde heute Abend und morgen dann mal etwas rumprobieren und meine Lösung (sofern vorhanden) hier mal preis geben, für den Fall das der ein oder andere auch eine ähnliche Lösung sucht und um ggf. meine Lösung zu besprechen / Verbesserungen besprechen.

    Bewertung ging vorher schon an alle beteiligten raus. Merci!


    Edit:
    Ich werd noch bekloppt. Ich krieg des einfach nicht zum laufen. Gibts ne Step-by-Step-Anleitung wie ich die QWT-Klassen in VS zum laufen bekomme? Ich hab jetzt soviel hin und her kopiert, sodass ich n Re-Install vornehmen muss, wenn ich die QWT Klassen entfernen will - das kann ja auch nicht richtig sein. Am Ende habe ich jetzt die Fehlermeldung, dass ich das Programm nicht starten kann, da ich ein ungültiges Dateiformat verwende. Dabei habe ich nur versucht in VS2010 ein QT-Sample zum laufen zu bringen >.<

    Spoiler
    Code:
    #include <qapplication.h> 
    #include <qlayout.h> 
    #include <qlabel.h> 
    #include <qpainter.h> 
    #include <qwt_plot_layout.h> 
    #include <qwt_plot_curve.h> 
    #include <qwt_scale_draw.h> 
    #include <qwt_scale_widget.h> 
    #include <qwt_legend.h> 
    #include <qwt_legend_item.h> 
    #include "cpupiemarker.h" 
    #include "cpuplot.h" 
     
    class TimeScaleDraw: public QwtScaleDraw 
    { 
    public: 
     TimeScaleDraw(const QTime &base): 
     baseTime(base) 
     { 
     } 
     virtual QwtText label(double v) const 
     { 
     QTime upTime = baseTime.addSecs((int)v); 
     return upTime.toString(); 
     } 
    private: 
     QTime baseTime; 
    }; 
     
    class Background: public QwtPlotItem 
    { 
    public: 
     Background() 
     { 
     setZ(0.0); 
     } 
     
     virtual int rtti() const 
     { 
     return QwtPlotItem::Rtti_PlotUserItem; 
     } 
     
     virtual void draw(QPainter *painter, 
     const QwtScaleMap &, const QwtScaleMap &yMap, 
     const QRect &rect) const 
     { 
     QColor c(Qt::white); 
     QRect r = rect; 
     
     for ( int i = 100; i > 0; i -= 10 ) 
     { 
     r.setBottom(yMap.transform(i - 10)); 
     r.setTop(yMap.transform(i)); 
     painter->fillRect(r, c); 
     
     c = c.dark(110); 
     } 
     } 
    }; 
     
    class CpuCurve: public QwtPlotCurve 
    { 
    public: 
     CpuCurve(const QString &title): 
     QwtPlotCurve(title) 
     { 
    #if QT_VERSION >= 0x040000 
     setRenderHint(QwtPlotItem::RenderAntialiased); 
    #endif 
     } 
     
     void setColor(const QColor &color) 
     { 
    #if QT_VERSION >= 0x040000 
     QColor c = color; 
     c.setAlpha(150); 
     
     setPen(c); 
     setBrush(c); 
    #else 
     setPen(color); 
     setBrush(QBrush(color, Qt::Dense4Pattern)); 
    #endif 
     } 
    }; 
     
    CpuPlot::CpuPlot(QWidget *parent): 
     QwtPlot(parent), 
     dataCount(0) 
    { 
     setAutoReplot(false); 
     
     plotLayout()->setAlignCanvasToScales(true); 
     
     QwtLegend *legend = new QwtLegend; 
     legend->setItemMode(QwtLegend::CheckableItem); 
     insertLegend(legend, QwtPlot::RightLegend); 
     
     setAxisTitle(QwtPlot::xBottom, " System Uptime [h:m:s]"); 
     setAxisScaleDraw(QwtPlot::xBottom, 
     new TimeScaleDraw(cpuStat.upTime())); 
     setAxisScale(QwtPlot::xBottom, 0, HISTORY); 
     setAxisLabelRotation(QwtPlot::xBottom, -50.0); 
     setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom); 
     
     /* 
     In situations, when there is a label at the most right position of the 
     scale, additional space is needed to display the overlapping part 
     of the label would be taken by reducing the width of scale and canvas. 
     To avoid this "jumping canvas" effect, we add a permanent margin. 
     We don't need to do the same for the left border, because there 
     is enough space for the overlapping label below the left scale. 
     */ 
     
     QwtScaleWidget *scaleWidget = axisWidget(QwtPlot::xBottom); 
     const int fmh = QFontMetrics(scaleWidget->font()).height(); 
     scaleWidget->setMinBorderDist(0, fmh / 2); 
     
     setAxisTitle(QwtPlot::yLeft, "Cpu Usage [%]"); 
     setAxisScale(QwtPlot::yLeft, 0, 100); 
     
     Background *bg = new Background(); 
     bg->attach(this); 
     
     CpuPieMarker *pie = new CpuPieMarker(); 
     pie->attach(this); 
     
     CpuCurve *curve; 
     
     curve = new CpuCurve("System"); 
     curve->setColor(Qt::red); 
     curve->attach(this); 
     data[System].curve = curve; 
     
     curve = new CpuCurve("User"); 
     curve->setColor(Qt::blue); 
     curve->setZ(curve->z() - 1); 
     curve->attach(this); 
     data[User].curve = curve; 
     
     curve = new CpuCurve("Total"); 
     curve->setColor(Qt::black); 
     curve->setZ(curve->z() - 2); 
     curve->attach(this); 
     data[Total].curve = curve; 
     
     curve = new CpuCurve("Idle"); 
     curve->setColor(Qt::darkCyan); 
     curve->setZ(curve->z() - 3); 
     curve->attach(this); 
     data[Idle].curve = curve; 
     
     showCurve(data[System].curve, true); 
     showCurve(data[User].curve, true); 
     showCurve(data[Total].curve, false); 
     showCurve(data[Idle].curve, false); 
     
     for ( int i = 0; i HISTORY; i++ ) 
     timeData[HISTORY - 1 - i] = i; 
     
     (void)startTimer(1000); // 1 second 
     
     connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)), 
     SLOT(showCurve(QwtPlotItem *, bool))); 
    } 
     
    void CpuPlot::timerEvent(QTimerEvent *) 
    { 
     for ( int i = dataCount; i > 0; i-- ) 
     { 
     for ( int c = 0; c NCpuData; c++ ) 
     { 
     if ( i HISTORY ) 
     data[c].data[i] = data[c].data[i-1]; 
     } 
     } 
     
     cpuStat.statistic(data[User].data[0], data[System].data[0]); 
     
     data[Total].data[0] = data[User].data[0] + 
     data[System].data[0]; 
     data[Idle].data[0] = 100.0 - data[Total].data[0]; 
     
     if ( dataCount HISTORY ) 
     dataCount++; 
     
     for ( int j = 0; j HISTORY; j++ ) 
     timeData[j]++; 
     
     setAxisScale(QwtPlot::xBottom, 
     timeData[HISTORY - 1], timeData[0]); 
     
     for ( int c = 0; c NCpuData; c++ ) 
     { 
     data[c].curve->setRawData( 
     timeData, data[c].data, dataCount); 
     } 
     
     replot(); 
    } 
     
    void CpuPlot::showCurve(QwtPlotItem *item, bool on) 
    { 
     item->setVisible(on); 
     QWidget *w = legend()->find(item); 
     if ( w && w->inherits("QwtLegendItem") ) 
     ((QwtLegendItem *)w)->setChecked(on); 
     
     replot(); 
    } 
     
    int main(int argc, char **argv) 
    { 
     QApplication a(argc, argv); 
     
     QWidget vBox; 
    #if QT_VERSION >= 0x040000 
     vBox.setWindowTitle("Cpu Plot"); 
    #else 
     vBox.setCaption("Cpu Plot"); 
    #endif 
     
     CpuPlot *plot = new CpuPlot(&vBox); 
     plot->setTitle("History"); 
     plot->setMargin(5); 
     
     QString info("Press the legend to en/disable a curve"); 
     
     QLabel *label = new QLabel(info, &vBox); 
     
     QVBoxLayout *layout = new QVBoxLayout(&vBox); 
     layout->addWidget(plot); 
     layout->addWidget(label); 
     
    #if QT_VERSION 0x040000 
     a.setMainWidget(&vBox); 
    #endif 
     
     vBox.resize(600,400); 
     vBox.show(); 
     
     return a.exec(); 
    } 
    

    Dieser Code dürfte laut Beschreibung meinem Problem bereits sehr nahe kommen und wäre daher denke ich perfekt geeignet.


    Edit: bis auf weiteres closed
     
  8. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.