Tkinter matplotlib-Diagramm kann nicht mit Schaltflächen und benutzerdefinierten Daten aktualisiert werden

Ich arbeite an der Schaffung eines Programms, das Tkinter und matplotlib nutzt. Ich habe 2 Listen von Listen (eine für x-Achse, eine für y-Achse) und ich schaue, um einen Knopf zu haben, der zwischen den Listen innerhalb der Liste wechseln kann. Ich habe viel von dem Code aus der Frage Interaktive Handlung auf Tkinter und Matplotlib , aber ich kann nicht die Grafik zu aktualisieren, wenn die Schaltfläche gedrückt wird. Ich bin ganz neu, um Klassen zu benutzen und ein bisschen Schwierigkeiten, sie zu verstehen.

tft ist die x-data tf1 die y-data in meinem code.

Beispiel für Daten:

x-data = [[1,2,3,4,5],[10,11,13,15,12,19],[20,25,27]]

y-data = [[5.4,6,10,11,6],[4,6,8,34,20,12],[45,25,50]]

Mein Code unten wird eine der Listen innerhalb einer Liste, aber wird nicht zwischen den Listen innerhalb dieser Liste wechseln, wenn die Schaltfläche gedrückt wird. Der korrekte Wert für event_num druckt auch im Befehlsfenster (die Ausgabe von event_num wurde in einer früheren Frage hier gelöst).

Es gibt keinen Fehler, der erscheint, das Programm druckt nur die Nummer (wenn die Taste gedrückt wird), aber aktualisiert das Diagramm nicht mit den neuen Daten aus der Liste.

Vorläufiger Code (keine Ausgaben – oder es sollte nicht sein)

 #Importing Modules import glob from Tkinter import * from PIL import Image from Text_File_breakdown import Text_File_breakdown import re import matplotlib.pyplot as plt from datetime import datetime #Initializing variables important_imgs=[] Image_dt=[] building=[] quick=[] num=0 l=0 match=[] #Getting the names of the image files image_names=glob.glob("C:\Carbonite\EL_36604.02_231694\*.jpeg") #image= Image.open(images_names[1]) #image.show() #Text_File_breakdown(file,voltage limit,pts after lim, pts before lim) tft,tf1,tf2=Text_File_breakdown('C:\Carbonite\EL_36604.02_231694.txt',3.0,5,5) #tft= time of voltages tf1=Voltage signal 1 tf2=Voltage signal 2 #Test Settings: 'C:\Carbonite\EL_36604.02_231694.txt',3.0,5,5 #Getting the Dates from the image names for m in image_names: Idt=re.search("([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}.[0-9]{2}.[0-9]{2})", m) Im_dat_tim=Idt.group(1) Im_dat_tim=datetime.strptime(Im_dat_tim, '%Y-%m-%d %H.%M.%S') Image_dt.append(Im_dat_tim) Im_dat_tim=None #Looking for the smallest difference between the voltage and image dates and associating an index number (index of the image_names variable) with each voltage time for event in range(len(tft)): for i in range(len(tft[event])): diff=[tft[event][i]-Image_dt[0]] diff.append(tft[event][i]-Image_dt[0]) while abs(diff[l])>=abs(diff[l+1]): l=l+1 diff.append(tft[event][i]-Image_dt[l]) match.append(l) l=0 #Arranging the index numbers (for the image_names variable) in a list of lists like tft variable for count in range(len(tft)): for new in range(len(tft[count])): quick.append(match[num]) num=num+1 building.append(quick) quick=[] plt.close('all') fig, ax = plt.subplots(1) ax.plot(tft[1],tf1[1],'.') # rotate and align the tick labels so they look better fig.autofmt_xdate() # use a more precise date string for the x axis locations in the # toolbar import matplotlib.dates as mdates ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d') plt.title('Single Event') 

Fortsetzung des Codes / Portion des Code, wo das Problem ist:

 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure import numpy as np class App: def __init__(self, master): self.event_num = 1 # Create a container frame = Frame(master) # Create 2 buttons self.button_left = Button(frame,text="< Previous Event", command=self.decrease) self.button_left.grid(row=0,column=0) self.button_right = Button(frame,text="Next Event >", command=self.increase) self.button_right.grid(row=0,column=1) fig = Figure() ax = fig.add_subplot(111) fig.autofmt_xdate() import matplotlib.dates as mdates ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d') self.line, = ax.plot(tft[self.event_num],tf1[self.event_num],'.') self.canvas = FigureCanvasTkAgg(fig,master=master) self.canvas.show() self.canvas.get_tk_widget().grid(row=1,column=0) frame.grid(row=0,column=0) def decrease(self): self.event_num -= 1 print self.event_num self.line, = ax.plot(tft[self.event_num],tf1[self.event_num],'.') self.canvas.draw() #self.canvas.draw(tft[self.event_num],tf1[self.event_num],'.') #self.line.set_xdata(tft[event_num]) #self.line.set_ydata(tf1[event_num]) def increase(self): self.event_num += 1 print self.event_num self.line, = ax.plot(tft[self.event_num],tf1[self.event_num],'.') self.canvas.draw() #self.canvas.draw(tft[self.event_num],tf1[self.event_num],'.') #self.set_xdata(tft[event_num]) #self.set_ydata(tf1[event_num]) root = Tk() app = App(root) root.mainloop() 

2 Solutions collect form web for “Tkinter matplotlib-Diagramm kann nicht mit Schaltflächen und benutzerdefinierten Daten aktualisiert werden”

Das Problem ist, dass Sie ständig auf einem anderen Satz von Achsen plotten, als Sie denken. self.line, = ax.plot(tft[self.event_num],tf1[self.event_num],'.') Bezieht sich auf die Achsen, die du außerhalb deiner Klasse erstellt hast, nicht die Achsen in der Figur, die du in der App Klasse erstellt hast . Das Problem kann behoben werden, indem man self.fig und self.ax Attribute erstellt:

 class App: def __init__(self, master): self.event_num = 1 # Create a container frame = Frame(master) # Create 2 buttons self.button_left = Button(frame,text="< Previous Event", command=self.decrease) self.button_left.grid(row=0,column=0) self.button_right = Button(frame,text="Next Event >", command=self.increase) self.button_right.grid(row=0,column=1) self.fig = Figure() self.ax = self.fig.add_subplot(111) self.fig.autofmt_xdate() import matplotlib.dates as mdates self.ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d') self.line, = self.ax.plot(tft[self.event_num],tf1[self.event_num],'.') self.canvas = FigureCanvasTkAgg(self.fig,master=master) self.canvas.show() self.canvas.get_tk_widget().grid(row=1,column=0) frame.grid(row=0,column=0) def decrease(self): self.event_num -= 1 print self.event_num self.line, = self.ax.plot(tft[self.event_num],tf1[self.event_num],'.') self.canvas.draw() def increase(self): self.event_num += 1 print self.event_num self.line, = self.ax.plot(tft[self.event_num],tf1[self.event_num],'.') self.canvas.draw() 

Ein anderes (mögliches) Problem besteht darin, dass die Daten an den Plot angehängt werden, anstatt ersetzt zu werden. Es gibt zwei Möglichkeiten, dies zu beheben:

  1. hold ab: self.ax.hold(False) irgendwo in __init__() bevor Sie etwas __init__() .
  2. Tauschen Sie die Plotdaten aus: Ersetzen Sie die Zeile

     self.line, = self.ax.plot(tft[self.event_num],tf1[self.event_num],'.') 

    mit

     self.line.set_xdata(tft[self.event_num]) self.line.set_ydata(tf1[self.event_num]) 

Sie plotten zu einer Achse im globalen Namensraum, aber die Zeichnung auf einem anderen, nicht zusammenhängenden globalen Objekt neu zu zeichnen. Ich denke, Ihre Fragen sind über globale vs lokalen Bereich und das self Objekt in objektorientierte Programmierung.

Python Scoping

Variablen, die in Ihrer Datei ohne Einrückung erstellt wurden, befinden sich im globalen Bereich einer Datei. class und def Anweisungen erstellen lokale Bereiche. Verweise auf einen Variablennamen werden durch Überprüfung der Bereiche in dieser Reihenfolge aufgelöst:

  • Lokaler Bereich
  • Umfassender lokaler Geltungsbereich (mit nur defs , nicht class )
  • Globaler Umfang
  • Builtins

Diese Kaskade ist nur für Referenzen . Zuordnungen zu einem Variablennamen Zuordnung zum aktuellen globalen oder lokalen Bereich, Zeitraum. Eine Variable dieses Namens wird im aktuellen Bereich angelegt, wenn sie noch nicht existiert.

Die Bindungen der lokalen Variablen werden gelöscht, wenn eine Funktion zurückkehrt. Werte, die nicht gebunden sind, werden schließlich Müll gesammelt. Wenn eine Zuweisung eine globale Variable an den Wert einer lokalen Variablen bindet, wird der Wert mit dem globalen Wert fortgesetzt.

Anwenden auf Ihren Code

Es gibt zwei Sätze von Zahlen- / Achsenobjekten, die in deinem Code erstellt wurden.

 # From your top chunk of code from Tkinter import * import matplotlib.pyplot as plt # This line creates a global variable ax: fig, ax = plt.subplots(1) # From your bottom chunk of code class App(self, master): def __init__(self, master): fig = Figure() # This line creates a local variable ax: ax = fig.add_subplot(111) # This line references the local variable ax: ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d') # This line references the local variable ax, and binds its value # to the attribute line of the self object, # which is the global variable app: self.line, = ax.plot(x[self.event_n],y[self.event_n]) def increase(self): self.event_num += 1 # This line references the global variable ax self.line, = ax.plot(x[self.event_n],y[self.event_n]) # This line updates the object's canvas but the plot # was made on the global axes: self.canvas.draw() app = App(root) 

Sie können dies beheben, indem Sie immer auf eine Achse verweisen, die mit Ihrem Tkinter-Root-Fenster verknüpft ist:

  • self.fig, self.ax = plt.subplots(1, 1) um dauerhafte Achsen zu erzeugen.
  • self.ax.cla() , um die Daten der vorherigen Auswahl zu entfernen
  • self.ax.plot() , um die Daten im aktuellen self.event_num Index self.event_num
  • self.ax.set_xlim(x_min*0.9, x_max*0.9) und self.ax.set_ylim(y_min*1.1, y_max*1.1) , um das self.ax.set_ylim(y_min*1.1, y_max*1.1) zu halten, um die Bewegung des Mittelwerts der Daten zwischen den inneren Listen zu visualisieren. Die x_max , y_max , x_min und y_min können vor der Hauptereignisschleife durch Abflachen der x- und y-Listen und dann mit builtins max() und min() .
  • Widgets anzeigen und verstecken
  • Gibt es einen bekannten Win32 Tkinter Bug in Bezug auf die Anzeige von Fotos auf einer Leinwand?
  • Wie erstellen Sie eine TKinter GUI Stop-Taste, um eine Endlosschleife zu brechen?
  • Wie kann ich die Ausgabe von tkFileDialog.askdirectory verwenden, um ein tkinter Entry-Feld zu füllen
  • Wie lösche ich das Entry-Widget, nachdem eine Schaltfläche in Tkinter gedrückt wurde?
  • Greifen Sie einen Rahmen aus, nachdem Sie auf einen Radiobutton Tkinter geklickt haben
  • Wie kann ich eine python-GUI mit einem XML-basierten Layout der GUI generieren?
  • Wie mache ich ToolTip mit Kivy?
  • Python Glade konnte kein GladeXML-Objekt erstellen
  • Python in Maya - Abfrage Checkbox Wert
  • Python gui veranstaltungen vergeben
  • Python ist die beste Programmiersprache der Welt.