Verfasst am: 17.12.2012, 11:35
Titel: Timer beim Schließen der GUI beenden
Hallo,
ich habe eine GUI und starte mit der einen Timer, um serielle Daten periodisch einzulesen. Natürlich muss ich den auch schließen, sonst bekomme ich beim Beenden der GUI den Fehler:
Der Timer an sich funktioniert übrigens einwandfrei, obwohl ich bisher noch nie mit Timern gearbeitet habe und mir die Syntax der TimerFcn auch ziemlich komisch vorkommt
Jemand ne Idee, was ich falsch mache?
Verfasst am: 17.12.2012, 14:28
Titel: Re: Timer beim Schließen der GUI beenden
Hallo CPU3,
Herzlich willkommen im Forum!
Dies ist ein Standard-Problem und es führt immer wieder zu Fehlern.
Der "handles"-Struct, der an die Callbacks mitgeliefert wird, ist nicht der aktuelle, sondern der, der zum Zeitpunkt des Erstellens des Callbacks existierte.
Das Mitliefern von "handles" an die Callbacks ist deshalb eine schlechte Idee.
Code:
function figure1_DeleteFcn(hObject, eventdata, handles)
handles = guidata(hObject);
stop(handles.timer);
delete(handles.timer)
Das Verwenden sinnvoller Namen wir "timer" ist immer viel besser als cryptische Abkürzungen wie "tmr". Die heutigen Rechner verfügen über GigaBytes, so dass das Weglassen der Vokale keinen messbaren Resourcen-Gewinn bringt. Dagegen ist das Lesen und Debuggen von Code immer noch an unsere computer-technisch beschränkten Gehirne gebunden.
vielen Dank für die Antwort.
Das mit der Bezeichnung habe ich eben geändert, hatte mir das so aus einem Beispiel geklaut und war zu faul, die zu ändern
Das mit den handles klingt logisch, damit kenne ich mich noch nicht gut aus, am Anfang ist das recht verwirrend Nach deiner Aussage wäre es dann auch besser, in die Funktion Initialize und jede andere in der zweiten Zeile auch zu schreiben
oder nicht? Weil darüber bekomme ich ja den handle, aus dem der Aufruf stammt!? Oder bekomme ich dadurch z.B. bei einem Button-Callback das handle des Buttons? Dann fliegt mir das aber um die Ohren, ohne die Zeile kann ich in Initialize und in allen anderen Funktionen korrekt auf den GUI-handle innerhalb der Funktion zugreifen, z.B. mit
Trotz alledem beendet sich der Timer immer noch nicht...
Hast du noch eine Idee was falsch sein könnte? Wahrscheinlich was so blödes, dass man das gar nicht erkennt
Auf jeden Fall bin ich jetzt mit den handles ziemlich verwirrt
Und hilft Dir die Dokumentation von "help guidata" weiter?
"handles" ist ein normaler STRUCT, der in einem Figure gespeichert wird. Zum auslesen kann man GUIDATA(H) verwenden, wobei H irgendein Handle eines Objekts in der figure sein kann, ein Plot-Objekt, ein AXES oder UICONTROL oder auch die Handle der Figure selbst.
Es wäre eine gute Entscheidung gewesen, diesen Struct nicht als Standard "handles" zu nennen, da sich dies ja nach einem Vector von Handels anhört.
wurde das Feld "timer" entweder nicht im handles Struct gespeichert, oder der handles Struct wurde danach nicht wieder in der Figure gespeichert, oder der verwendete handles Struct ist nicht der aktuelle, sondern einer, der gespoeichert wurde, während der handles Struct noch gar nicht fertiggestellt worden ist, z.B. während der Erstellung des GUIs.
ja, ich hab mir das noch ein paar Mal durchgelesen und auch bisschen gegooglet und denke, dass ich das nun besser verstanden habe. Mit der Benennung sollte ich dann wohl in Zukunft etwas mehr aufpassen...
Nichts desto trotz finde ich da keinen Fehler, scheinbar will mich Matlab verarschen Hier eine modifizierte Version von meinem Code:
function figure1_DeleteFcn(hObject, eventdata, handles) % hObject handle to figure1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA)
handles = guidata(hObject);
display(handles.bla)
stop(handles.timer);
delete(handles.timer);
Hast du eine Idee, wieso das so ist oder habe ich da irgendeinen dummen Fehler gemacht? bla und timer unterscheiden sich ja nur im Datentyp, aber wurden an der gleichen Stelle auf gleiche Art und Weise gespeichert!?
Ich finde die Übergabe des "handles" als Input-Argument sehr verwirrend. Üblicherweise sind diese Structs aus den Inputs unvollständig, da die Callbacks während der Erstellung des GUIs erzeugt werden. Dann lässt man die "handles" dort doch lieber mal weg und besorgt sie sich dynamisch per GUIDATA.
Ich verstehe nicht, wo "guidata(handles.output,handles)" den neuen "handles" Struct genau abspeichert: Was ist "handels.output"?
Wieso testest Du nun die DeleteFcn? Traten die Probleme nicht zunächst an anderer Stelle auf?
Es könnte hilfreich sein, wenn Du in den Source von GUIDATA einen Breakpoint setzt und Schritt für Schritt betrachtest, von wo diese Funktion mit welchem Struct aufgerufen wird. Denn ich kann Dir versichern, dass Matlab dies vollkommen deterministisch ausführt. Immer wenn man sich als Programmierer von Matlab hintergangen fühlt, sollte man es (zur Strafe) ausschalten, einen Kaffee trinken und es mit klarem Kopf wieder neu starten. Die Probleme lösen sich dabei überraschend oft von alleine, wenn man z.B. vergessen hat ein M-File zu speichern und die vorherige Version läuft, während man eine andere im Editor sieht...
erstmal zu den Fragen: handles.output ist das handle auf figure1, das habe ich in in der OpeningFcn der GUI gesetzt. Und der Fehler trat doch schon die ganze Zeit bei der DeleteFcn auf, dort wollte ich den Timer ja beenden.
Daran, dass man GUIs debuggen kann, hab ich nun gar nicht gedacht
So habe ich den Fehler auch nun gefunden und du lagst mit deiner Vermutung schon recht Nahe. Ich habe den Timer ja wie folgt definiert:
Also übergab ich das aktuelle handles (wohl statisch!?) in den Timer. Dort befand sich zu dem Zeitpunkt der Timer selber offenbar noch gar nicht. In der TimerFcn habe ich dann das mitgegebene handles (was ja alt war) in der GUI gespeichert. Da das ein altes handles war, wurde das neue überschrieben, wodurch handles.timer nicht mehr existierte. Komischerweise wurden andere Variablen, die bereits im alten handles existierten, aber einen neuen Wert bekommen haben, mit dem neuen Wert übernommen!? Ist wohl einfach so... Oder kannst du mir das erklären, wieso das so ist?
Nun läuft alles einwandfrei und ich habe endgültig verstanden, warum man sich die handles dynamisch holen sollte
Das mit dem statischen Übergeben hatte ich so irgendwo aus einem Beispiel, das wohl jemand erstellt hatte, der selber keine Ahnung hatte...
Vielen Dank für die Hilfe, selber wäre ich da nie drauf gekommen.
Viele Grüße
Björn
Einstellungen und Berechtigungen
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.