Effizienteres Malen mit QPainter

Alles rund um die Programmierung mit Qt
Antworten
omegano
Beiträge: 21
Registriert: 18. Mai 2012 18:32

Effizienteres Malen mit QPainter

Beitrag von omegano »

Hallo, ich habe mir ein kleines Programm geschrieben um einfach den Verlauf meines Cursors nachzuzeichnen.
Allerdings glaube ich das alles andere als sehr effektiv bzw ressourcen schonend ist.
Und ich hab nur eine Ahnung wie ich es verbessern könnte,
ich hab es auch schon tot gegoogled leider sagt dort auch jeder was anderes.

Hier mein bisheriger Code:

Code: Alles auswählen

void Widget::mouseMoveEvent(QMouseEvent *e)
{
    punkte.append( e->pos() );
    qDebug() << punkte;
    update();
}

void Widget::paintEvent(QPaintEvent *e)
{
    QPainter p(this);
    QPen myPen;
    myPen.setColor( QColor(255,0,0) );
    p.setPen(myPen);

    foreach(QPoint poi,punkte){
        p.drawPoint(poi);
    }
    p.end();
}
Also momentan Updatet er ja quasi nach jedem Punkt bzw nach jedem durchlaufen des Events die komplette Zeichnung.

Ideen:
1)Ich habe daran gedacht evtl event neu zu implementieren und einen Ereignisfilter einzufügen der nur nach dem Loslassen der Taste einmal das Widget updatet.
2)Ich habe durch Google + ein bisschen Dokumentation lesen erfahren, das ich auch auf ein Labelzeichnen kann, mir diese "Zeichnung" als Pixmap speichern und dann die Pixmap + die neuen Punkte zeichnen kann, allerdings weis ich nicht inwiefern dies effizient ist oder nicht.


Ich hoffe das ihr mir sagen könnt welche der beiden Versionen die effizientere ist oder mir am besten eine noch besseren Denkanstoß geben auf den ich nicht gekommen bin bisher.

Danke
Mfg omegano
odt
Beiträge: 128
Registriert: 12. August 2010 11:49
Kontaktdaten:

Re: Effizienteres Malen mit QPainter

Beitrag von odt »

Hallo Omegano

Dem QWidget::Update kannst Du den neu zu zeichnenden Bereich übergeben. Diesen kannst Du anschliessend im Paint über PaintEvent::rect()::contains( poi ) abfragen. Ob Du damit jedoch eine bessere Performance herausholst müsstest Du testen.

1) ist sicher schneller, da kein Repaint... Aber gewollt?
2) ist "komisch", zwar kann QLabel ein Bild anzeigen, aber das dünkt mich etwas abwegig, aber der Hintergedanke ist interessant.

Die Frage ist, was das eigentliche Problem ist. Dass die Punkte-Liste zu gross wird? (Evt. doppelte Punkte vermeiden) Dass das drawPoint zu langsam ist? (Caching (3), direkte Bitmap-Manipulation (4))

3) Warum nicht ein Bitmap als Cache verwenden, d.h. ein Solches erstellen, im mouseEvent via QPainter painter( image ) den "neuen" Punkt ins Image drawen. Im Paint dann anschliessend das Image anstelle der Punkte drawen. Da das Update nicht ein direktes repaint zur Folge hat, sollte es so relativ schnell sein.

4) Oder Du könntest das Bitmap direkt via Memory (Qimage::bits) manipulieren.

Viele Grüsse
Reto
ODT Informatik GmbH, Reto Tschofenig
omegano
Beiträge: 21
Registriert: 18. Mai 2012 18:32

Re: Effizienteres Malen mit QPainter

Beitrag von omegano »

Also mein Problem ist ganz einfach, das mein Programm am Ende extrem langsam wird, manchmal friert mir die IDE ein am Ende(wenn zuviele Punkte gemalt werden).
1) ist sicher schneller, da kein Repaint... Aber gewollt?
gewollt ist das ich einfach den Mausverlauf erstmal nachmale, bis ein reset durch einen Knopfdruck oder ähnliches aufgerufen wird.
2) ist "komisch", zwar kann QLabel ein Bild anzeigen, aber das dünkt mich etwas abwegig, aber der Hintergedanke ist interessant.
habe es jetzt mal versucht indem ich mir eine eigene label erweiterung geschrieben habe, allerdings hackt es noch ein bisschen mit dem hin und her schieben des Pixmaps.
Wirkt auf mich auch vom Code her irgendwie nicht Elegant, ist mMn nach ne ziemliche Flickschusterei. Wenn ichs fertig habe werde ich einfach mal der Vollständigkeit halber Posten obs nen Performance gewinn zur Folge hatte.
3) Warum nicht ein Bitmap als Cache verwenden, d.h. ein Solches erstellen, im mouseEvent via QPainter painter( image ) den "neuen" Punkt ins Image drawen. Im Paint dann anschliessend das Image anstelle der Punkte drawen. Da das Update nicht ein direktes repaint zur Folge hat, sollte es so relativ schnell sein.
Im mouseEvent kann ich aber doch nicht malen, soweit ich das aus meinem Buch richtig verstanden habe oder?
Oder meinst du das ich die Bitmap einfach Erstelle, und dann später im PaintEvent male?
Dafür müsste ich dann aber den QPainter als Member erstellen also im Header schon aufführen und nicht erst im paintEvent?
4) Oder Du könntest das Bitmap direkt via Memory (Qimage::bits) manipulieren.
hört sich interessant an aber dafür müsste ich mir erstmal die Doku dazu ein bisschen zu gemühte führen^^

danke für deine hilfe.
odt
Beiträge: 128
Registriert: 12. August 2010 11:49
Kontaktdaten:

Re: Effizienteres Malen mit QPainter

Beitrag von odt »

Morning

Regel Nr 1 beim Optimieren: den Flaschenhals identifizieren und nicht unnötig optimieren...

ich habe es kurz mal probiert und auf meiner (nicht sehr schnellen) Kiste läuft das Programm mit rund 200'000 Punkten flüssig mit über 40 fps.
friert mir die IDE ein
deutet auf ein "anderes" Problem. Normalerweise sollte die Ausführung eines Programmes die IDE nicht beeinflussen, ausser im Zusammenhang mit Debugging. Und da gibt es eine Zeile, die in diesem Zusammenhang auffällt...

Code: Alles auswählen

qDebug() << punkte;
gibt alle Punkte aus, und das gibt ganz schön viel Debug-Ausgaben.

3)
Mit dem QPainter kannst Du auf ein Widget zeichnen, aber normalerweise wie Du sagtest nur im Paint-Event. Allerdings kann man mit einem QPainter auch auf den Drucker oder in ein Bitmap zeichnen. D.h. Du erstellst zuerst ein QImage. Dann im MouseMove einen QPainter aufs Image. Den neuen Punkt zeichnen. Im Paint-Event dann nicht alle Punkte sondern drawImage. Damit habe ich konstante 100 fps.
Den Painter würde ich vom Gefühl her nicht als Member speichern.

4)
Mach's nur, wenn Du Dein Memory im Griff hast. Wird performance-mässig im Vergleich zu 3) nicht viel bringen.

Gruess, Reto
ODT Informatik GmbH, Reto Tschofenig
omegano
Beiträge: 21
Registriert: 18. Mai 2012 18:32

Re: Effizienteres Malen mit QPainter

Beitrag von omegano »

danke, das mit der IDE Lag echt am Debuggen, hatte die Debug ausgabe für hier allerdings rausgekürzt wollte, nicht Programmrelevanten Code rauschmeissen. Was allerdings komisch war, er hatte alle Punkte schön unten rein geschrieben. Erst beim beenden hat sich das negativ auf die IDE ausgewirkt. Naja egal jetzt klappts ja ohne einfrieren. :) Hast mir sehr geholfen, ich werde wohl mit den Lösungansätzen nochwas brauchen, da mir die Uni momentan leider wenig Zeit lässt meinem Freizeitspaß Qt zu fröhnen ;)
Antworten