Laufendes Diagramm schneller machen -- ohne flackern

Plattformunabhängige GUIs mit wxWidgets.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 11. November 2008, 22:57

Hallo!

Bild

Unter Windows wird dieses "laufende Diagramm" langsamer, wenn man das Frame vergrößert. Unter Windows wird zuerst im Speicher in ein Bitmap gezeichnet. Dieses wird dann automatisch vom wx.BufferedPaintDC in das wx.Window "geblittet". Zeichnet man direkt auf den wx.PaintDC, dann wird das Diagramm zwar schneller gezeichnet, aber es fängt zu flackern an.

Unter Linux kümmert sich GTK selber um das Buffern. Deshalb läuft das Diagramm unter Linux, auch wenn ich es groß mache, noch ziemlich flüssig. Und es flackert auch nicht.

Damit wxPython unter Linux sich nicht selber um das Buffern kümmert, habe ich im Code statt ``dc = wx.BuffertPaintDC(self)`` ``dc = wx.AutoBufferedPaintDCFactory(self)`` verwendet.

Was könnte man tun, um dieses "laufende Diagramm" unter Windows, wie auch unter Linux so richtig schnell und ressourcenschonend zu programmieren? Bringt es was, wenn man OpenGL verwendet? Ich frage, weil ich das nicht so schnell ausprobieren kann. Ich müsste mich erst in OpenGL einarbeiten (wahrscheinlich mindestens ein paar Tage) um dieses Diagramm vielleicht auch in OpenGL hin zu bekommen.

CODE AUSGELAGERT: http://paste.pocoo.org/show/90968/

lg
Gerold
:-)

Suchworte: Graph Balkendiagramm animiert
Zuletzt geändert von gerold am Mittwoch 12. November 2008, 17:49, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Mittwoch 12. November 2008, 11:10

Hoi Gerold,

denke das Du das Problem ziemlich genau erkannt hast. Auf der MPL-Seite gibt es bei den Beispiel zwei wx-Beispiele zum Thema Animation. Ggf. ist da eine Lösung dabei. (Kann das gerade nicht ausprobieren, da nicht am Arbeitsplatz. Wäre aber neugierig, ob es klappt.)

OpenGL ist sicher eine Alternative. Aber ich habe mich selber noch nicht so weit eingearbeitet, dass ich eine Lösung bieten könnte. Sorry.

Gruß,
Christian
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 12. November 2008, 11:21

CM hat geschrieben:OpenGL ist sicher eine Alternative. Aber ich habe mich selber noch nicht so weit eingearbeitet, dass ich eine Lösung bieten könnte. Sorry.
OpenGL ist unter Linux insofern manchmal ein Problem, da nicht alle Treiber haben, die es unterstützen. Insbesondere Leute die Wert auf freie Treiber setzen, haben manchmal keine 3D-Beschleunigung.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Mittwoch 12. November 2008, 11:25

Stimmt - das Problem kenne ich, denke aber immer so lange nicht daran, wie ich das System nicht update. Da ich selber unbedingt 3D-Graphik brauche und daher die entsprechenden Treiber verwende, habe ich an diese Einschränkung nicht gedacht. Danke für den Hinweis.
Allerdings gehe ich davon aus, dass dies für die meisten Leute keine Einschränkung ist, weil sie die nötigen Treiber besitzen. Wäre natürlich für den anzusprechenden Nutzerstamm abzuklären.

Gruß,
Christian
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 12. November 2008, 12:44

Hallo Christian!
Hallo Leonidas!

Der Tipp, es mal mit Matplotlib zu versuchen ist keine schlechte Idee. Ich werde das auf jeden Fall noch genauer untersuchen.

Aber eigentlich geht es mir erst mal darum, herauszufinden welche Möglichkeiten es gibt, schnelle 2D-Grafik in eine wxPython-Anwendung einzubetten. Und das Hauptanliegen ist es, endlich mal herauszufinden, ob es eine Möglichkeit gibt, das Zeichnen zu beschleunigen. Wenn OpenGL die Grafikausgabe verbessert, dann mache ich das. Aber jeder spricht in Verbindung mit OpenGL immer nur von 3D. Es geht mir nicht um 3D, sondern rein um das schnellstmögliche Zeichnen (ohne Flackern) von 2D-Grafiken.

Ich möchte das zukünftig in mehreren Anwendungen einsetzen können.
Z.B. um Messwerte (Oszilloskop; 10.000 Messwerte die Sekunde) entgegenzunehmen und animiert auszugeben.
Oder um ein 2D-CAD-Programm (Schaltplaneditor, Platinenlayout) schreiben zu können, welches auch bei vielen Objekten nicht ruckelt.
Oder wie 'Nko' es in einem anderen Thread angesprochen hat, Musikfrequenzen in Echtzeit so detailliert wie möglich darzustellen/animieren.

Also ich denke, dass ich dafür wahrscheinlich irgendeine Hardwarebeschleunigung brauchen werde. Würde es etwas bringen, sich in OpenGL einzuarbeiten? Oder gibt es viel einfachere/bessere Alternativen? Oder bin ich auf dem Holzweg und OpenGL bringt nur etwas, wenn ich 3D brauche? Ist es überhaupt nötig, sich OpenGL anzutun, nur um Hardwarebeschleunigung zu bekommen?

lg
Gerold
:-)

PS: Ich hatte auch schon kurz überlegt, mich in PyGame einzuarbeiten. Das soll man auch in eine wxPython-Anwendung einbetten können. Aber irgendwie bin ich mir noch nicht sicher, ob das die Lösung wäre.

.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Mittwoch 12. November 2008, 13:55

Pyglet lässt sich glaube ich ganz gut einbetten und ist wesentlich angenehmer als Pygame ;)
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 12. November 2008, 14:47

Also Cairo soll zumindest laut Selbstbeschreibung und Wikipedia Hardwarebeschleunigung (wenn verfügbar, also nicht so wie bei OpenGL, zwingend) bieten. Gibt es sowohl für Unices als auch für Windows, Python-Bindings gibt es auch. Wird inzwischen extensiv von FIrefox benutzt (SVG und Canvas in FF2, ab FF3 wird alles über Cairo geleitet), ebenso wird es von GTK+ stark verwendet (vielleicht ist deine Applikation deswegen unter Linux ausreichend schnell).

Alternativ auch AGG, aber ich weißt nicht ob das Hardwarebeschleunigung bietet. Da stehen auch eher weniger Leute dahinter.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 12. November 2008, 16:29

Leonidas hat geschrieben:Also Cairo soll [...] Hardwarebeschleunigung [...] bieten. [...] (vielleicht ist deine Applikation deswegen unter Linux ausreichend schnell
Hallo Leonidas!

Danke für diesen Hinweis! :-) Ich werde das auf jeden Fall ausprobieren. Denn Cairo kann man in wxPython mit ``wx.lib.wxcairo`` direkt auf einen DC mappen.

Ich hatte es nur vorzeitig aufgegeben, die Cairo-Beispiele in der wxPython-Demo unter Windows zum Laufen zu bekommen. Aber inzwischen habe ich es geschafft. Das was ich da zu sehen bekomme, sieht auf den ersten Blick schon mal ziemlich schnell aus.

Damit Cairo läuft, habe ich GTK installiert. Das soll die einfachste Möglichkeit sein, Cairo unter Windows zum Laufen zu bekommen. Falls es jemanden interessiert... ich habe diese Dateien in dieser Reihenfolge installiert:
- gtk-2.12.9-win32-1.exe
- gtk-2.12.9-win32-2.exe
- pycairo-1.4.12-1.win32-py2.5.exe
- pygobject-2.14.1-1.win32-py2.5.exe
- pygtk-2.12.1-2.win32-py2.5.exe
Gut, dass ich noch mit Python 2.5 arbeite. Denn für 2.6 habe ich keine Module entdeckt.

Wenn alles geklappt hat, dann kann man die Cairo-Demo in der wxPython-Demo ansehen.

Ich werde in den nächsten Tagen mal versuchen, das oben gezeigte "laufende Diagramm" direkt mit Cairo zu zeichnen. Dann werden wir sehen, ob es auch unter Windows den erwarteten Performanceschub bringt. Zumindest hoffe ich es. Denn Cairo lässt sich einfach einbinden und, so wie es aussieht, auch ziemlich einfach programmieren.

Also, vielen Dank erst mal,
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 12. November 2008, 17:52

Hallo Leute!

Also der Unterschied unter Windows ist enorm. Ich habe das Beispiel so umgeschrieben, dass es direkt die Cairo-Methoden zum Zeichnen verwendet. Jetzt kann ich das Fenster sogar auf volle Bildschirmgröße vergrößern und der Computer geht trotzdem nicht in die Knie.

Hier das Beispiel mit Cairo:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import wx
import random
import wx.lib.wxcairo

wx.SetDefaultPyEncoding("iso-8859-15")


class DisplayWindow(wx.Window):
    
    def __init__(self, parent):
        wx.Window.__init__(self, parent)
        self.Bind(wx.EVT_PAINT, self.on_self_paint)
        self.datalist = []
        self.timer = wx.Timer()
        self.timer.Bind(wx.EVT_TIMER, self.on_timer)
        self.timer.Start(50)
    
    
    def on_timer(self, event):
        self.datalist.append(random.randint(1, 100))
        if len(self.datalist) > 100:
            self.datalist.pop(0)
        self.Refresh(False)
    
    
    def on_self_paint(self, event):
        event.Skip()
        (width, height) = self.GetClientSizeTuple()
        gap = width / 101.0
        
        dc = wx.AutoBufferedPaintDCFactory(self)
        cr = wx.lib.wxcairo.ContextFromDC(dc)
        cr.set_line_width(2)
        
        # Weißer Hintergrund
        cr.set_source_rgb(1.0, 1.0, 1.0) # weiß
        cr.rectangle(0.0, 0.0, width, height)
        cr.fill()
        
        # Grüne Linien
        cr.set_source_rgb(0, 1, 0)
        datalist = self.datalist[:]
        for index, value in enumerate(datalist):
            x = (index + 1) * gap
            y = (height - (height / 100.0 * value)) * -1.0
            cr.move_to(x, height)
            cr.rel_line_to(0, y)
        cr.stroke()


class MyFrame(wx.Frame):
    
    def __init__(
        self, parent = None, title = "Example", size = wx.Size(200, 100)
    ):
        wx.Frame.__init__(self, parent, -1, title, size = size)
        display_window = DisplayWindow(self)


def main():
    """Testing"""
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
Nur schade, dass derzeit der http://cairographics.org/ Server nicht funktioniert. Aber mit Hilfe dieser beiden Dokumente konnte ich dann doch noch herausfinden, wie es funktioniert:

- http://www.tortall.net/mu/wiki/CairoTutorial
- http://www.tortall.net/mu/wiki/PyGTKCairoTutorial

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 12. November 2008, 18:27

...und wenn man mal wissen will, wie schnell das Diagramm laufen könnte:

http://paste.pocoo.org/show/90972/ :-)

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Donnerstag 13. November 2008, 13:17

Beeindruckend! Und Cairo ist eine schöne Idee, sollte ich mich wohl auch mal mit beschäftigen!

Zwei Dinge noch: OpenGL kann man natürlich auch zur Beschleunigung von 2D-Graphiken verwenden. Und der Hauptentwickler von MPL, John Hunter, hat ursprünglich im Sinn gehabt einen EEG-Viewer zu schreiben (hier, ganz unten), verläßt sich dabei aber wohl auf GTK.

Habe nie so schnelle Daten Plotten müssen, wx mit MPL hat immer gereicht ...

Besten Gruß und Danke für den Code,
Christian
Nko
User
Beiträge: 13
Registriert: Sonntag 19. Oktober 2008, 18:02

Sonntag 16. November 2008, 20:48

nabend zusammen.

zunächst mal ein kleiner Hinweis für Ubuntunutzer: Die Unterbibliothek wx.lib.wxcairo existiert erst ab Version 2.8.9.0 und Standardubuntu hängt da hinterher. Hier (http://wiki.wxpython.org/InstallingOnUbuntuOrDebian) steht wie man die aktuelle Version bequem installiert.

Mit der funktioniert's dann. Ich habe eigentlich alle obigen Programme ausprobiert. Sieht gut aus, flackert nicht, schön flüssig. Aber es ist immer das Gleiche: Nach dem Start dauert es ungefähr 7 Sekunden bis die grünen Streifen den rechten Rand erreichen. Im Vollbildmodus dauert es bestimmt doppelt so lange. (Linux auf 1.4 Centrino, ATI-Karte ohne propietären Treiber.) Das reicht mir nicht, die Leistung des Rechners sollte mehr bringen. Oder?

Achso, die Beispiele von http://matplotlib.sourceforge.net/examples/index.html befriedigen auch nicht 100%, manche machen im Vollbild totalen Mist. Naja.

Ich hab da mal was zusammengefrickelt, was zwar Cairo nutzt, aber per pygtk und nicht wx. Gehört also nur halb hier rein, versucht aber auch ein "laufendes Diagramm" ohne flickern. Klein siehts ganz gut aus,aber schon bei 1024x768 ruckelts ein bisschen und die idle-Funktion wird schon zu selten aufgerufen. Da muß ich mir was besseres einfallen lassen. Der Code (http://paste.pocoo.org/show/91380/) basiert auf dem Cairo-Beispielgesicht. Um parallel dazu etwas auszurechnen muß man sich da wohl threading einfahren? Oder doch pygame? Oder wie. GL? Sprites? Also ich bin immernoch konfus...
Nko
User
Beiträge: 13
Registriert: Sonntag 19. Oktober 2008, 18:02

Sonntag 16. November 2008, 20:52

eine Sache noch: das letzte Beispiel von Gerold flutscht richtig schön, bei größeren Fenstern hängt die Geschwindigkeit von der Höhe des Fensters ab! Na ich schau mich mal noch um..
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 17. November 2008, 00:06

Nko hat geschrieben:ATI-Karte ohne propietären Treiber
Und du bist sicher, dass diese Hardwarebeschleunigung bieten? Ansonsten ist natürlich Cairo wohl kaum schneller als irgendwas anderes.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
lunar

Montag 17. November 2008, 00:11

Leonidas hat geschrieben:
Nko hat geschrieben:ATI-Karte ohne propietären Treiber
Und du bist sicher, dass diese Hardwarebeschleunigung bieten?
Die freien Treiber bieten 3D-Beschleunigung für alte Karten. Iirc sind das alle Radeon-Modelle, die noch kein X im Namen tragen. Allerdings ist die Performance ziemlich schlecht, mit fglrx lässt sich da sicherlich noch was erreichen.
Antworten