wie pylab-plot in echtzeit aktualisieren?

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
Benutzeravatar
dall♀
User
Beiträge: 12
Registriert: Dienstag 23. März 2010, 15:44

nach meinem letzten, leider unbeantworteten post bin ich etwas weiter vorangekommen und die probleme sitzen woanders, vielleicht kann mir ja jetzt jemand helfen.

jetzt erstmal die vorgeschichte, dann meine fragen.

von meinem hauptprogramm aus erstelle ich ein neues objekt meiner eigenen klasse Plotting, die von threading.Thread erbt. der thread wird dann vom hauptprogramm aus gestartet, das natürlich parallel weiterläuft:

Code: Alles auswählen

plot = Plotting(tmpFilePath, unit, scanKeys, plotKeys)
plot.start()
einfaches plotten ohne zeitliche aktualisierung funktioniert ohne probleme und zwar sinngemäß so:

Code: Alles auswählen

def run(self):

        # (...)

        pylab.ion()                    # interactive mode on
        fig = pylab.figure(id)      # figure erstellen
        
        # daten für die plots aus datei holen usw., werden dann gespeichert im dictionary self.__data/self.__timestamps
        self.__initPlots()
        
        # zeichnen
        for key in self.__plotKeys:
            line, = pylab.plot(self.__timestamps, self.__data[key], label=Globals.CONFIGFILE.Channels[key].Name)
            self.__lines[key] = line
        
        pylab.draw()
dann wird die figure angezeigt und nach dem schließen läuft das hauptprogramm normal weiter.

ABER:

für den fall, dass der benutzer einen plot sehen will, der sich kontinuierlich aktualisiert, geht es mit einer schleife weiter:

Code: Alles auswählen

while True:
                self.__getData()                               # neue daten holen und self.__data/self.__timestamps aktualisieren
   
                ''' # methode 1
                for key in self.__plotKeys:
                    self.__lines[key].set_xdata(self.__timestamps)
                    self.__lines[key].set_ydata(self.__data[key])
                '''
                # methode 2
                for key in self.__plotKeys:
                    del self.__lines[key]
                    line, = pylab.plot(self.__timestamps, self.__data[key], label=Globals.CONFIGFILE.Channels[key].Name)
                    self.__lines[key] = line
                
                pylab.draw()
meine probleme:

- methode 1 funktioniert überhaupt nicht, das programm friert ohne fehlermeldung ein. warum?
- methode 2 aktualisiert die linien fortlaufend, aber sie wechseln immer die farbe, als würden immer neue plots hinzugefügt werden (daher der versuch des löschens mit del self.__lines[key] - scheint aber nichts zu bringen)
- wie kann ich den klick auf das X des plot-fensters abfangen, um die schleife zu beenden? sonst läuft der thread ja bis in alle ewigkeit weiter.
- warum bringt der erste klick auf den plot-button im hauptprogramm immer keinen plot hervor, obwohl der thread gestartet wurde (danach geht es aber, also mit dem zweiten klick)? habe dazu auch versucht, unterschiedliche backends zu benutzen (matplotlib.use('GTK'), matplotlib.use('GtkAgg'), matplotlib.use('TkAgg')), aber alles funktioniert.. naja, unterschiedlich schlecht. wer dazu mehr wissen will, dem kann ich auch noch fehlermeldungen präsentieren.

hat jemand auch nur einen klitzekleinen tipp zu irgendeinem problem davon für mich? hab ich irgendwas übersehen?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Einer der klitzekleinen Tipps ist: GUI-Toolkits und Threads = keine gute Idee, da sie nicht threadsicher sind. Daher sind die Updates immer von dem Thread auszuführen, in dem man die GUI laufen lässt. Und meist, bei kurzen Interaktionen ist es nicht notwendig Threads zu verwenden, da kann man üblicherweise via ``idle_add`` oder ``timeout_add`` Code ausführen lassen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
dall♀
User
Beiträge: 12
Registriert: Dienstag 23. März 2010, 15:44

hallo leonidas,
danke für deinen tipp. hab den plot jetzt als eigenes programm angelegt und übergebe ihm das datafile per kommandozeile. jetzt funktioniert alles anstandslos. ein bisschen entsetzt bin ich schon, wie viel probleme das machen kann ;)
Antworten