WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Timer beim Schließen der GUI beenden

 

CPU3
Forum-Newbie

Forum-Newbie


Beiträge: 4
Anmeldedatum: 17.12.12
Wohnort: Bremen
Version: ---
     Beitrag Verfasst am: 17.12.2012, 11:35     Titel: Timer beim Schließen der GUI beenden
  Antworten mit Zitat      
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:

Code:
??? Error while evaluating TimerFcn for timer 'timer-1'
Invalid handle object.


Also beende ich vorher den Timer, aber irgendwie greife ich darauf wohl falsch zu, weil das zu dem Fehler führt:

Code:
??? Reference to non-existent field 'tmr'.


Zum Code: In der OpeningFcn der GUI starte ich Initialize:

Code:
function gui_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
Initialize(hObject, handles);
handles=guidata(handles.output);


Dort wird unter anderem der Timer gestartet:

Code:
function handles = Initialize(hObject, handles)
handles.tmr = timer('TimerFcn', @(src,event)receive(src,event,hObject,handles) ,'BusyMode','Queue','ExecutionMode','FixedRate','Period',0.01);
start(handles.tmr);
guidata(handles.output,handles);


Nun will ich den wie folgt beim Schließen der GUI beenden:

Code:
function figure1_DeleteFcn(hObject, eventdata, handles)
stop(handles.tmr);


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 Wink
Jemand ne Idee, was ich falsch mache?

Vielen Dank
Private Nachricht senden Benutzer-Profile anzeigen


Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 17.12.2012, 14:28     Titel: Re: Timer beim Schließen der GUI beenden
  Antworten mit Zitat      
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.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
CPU3
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 4
Anmeldedatum: 17.12.12
Wohnort: Bremen
Version: ---
     Beitrag Verfasst am: 18.12.2012, 09:52     Titel:
  Antworten mit Zitat      
Hallo Jan,

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 Wink

Ansonsten bekomme ich weiterhin

Code:
??? Reference to non-existent field 'timer'.


Das mit den handles klingt logisch, damit kenne ich mich noch nicht gut aus, am Anfang ist das recht verwirrend Wink Nach deiner Aussage wäre es dann auch besser, in die Funktion Initialize und jede andere in der zweiten Zeile auch zu schreiben

Code:
handles = guidata(hObject);


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

Code:
set(handles.test,'string','bla');


Wenn "test" eine Textbox in der GUI ist.

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 Wink
Auf jeden Fall bin ich jetzt mit den handles ziemlich verwirrt Rolling Eyes

Viele Grüße
Björn
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 18.12.2012, 21:13     Titel:
  Antworten mit Zitat      
Hallo CPU3,

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.

Wenn Du dies bekommst:
Code:
??? Reference to non-existent field 'timer'.

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.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
CPU3
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 4
Anmeldedatum: 17.12.12
Wohnort: Bremen
Version: ---
     Beitrag Verfasst am: 19.12.2012, 09:12     Titel:
  Antworten mit Zitat      
Hallo Jan,

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 Wink Hier eine modifizierte Version von meinem Code:

Code:
function handles = Initialize(hObject, handles)
handles.bla = 1242;
handles.timer = timer('TimerFcn', @(src,event)receive(src,event,hObject,handles) ,'BusyMode','Queue','ExecutionMode','FixedRate','Period',0.01);
start(handles.timer);
guidata(handles.output,handles);


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);


Man sollte doch nun meinen, es handelt sich um die selben handles-structs aus der selben figure, oder nicht!? Daher wäre ja als Ausgabe zu erwarten

Code:
??? Reference to non-existent field 'bla'.


oder habe ich da einen Denkfehler?
Aber Pustekuchen, stattdessen gibts

Code:
ans =

        1242

??? Reference to non-existent field '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!?

Viele Grüße
Björn
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 19.12.2012, 17:34     Titel:
  Antworten mit Zitat      
Hallo CPU3,

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...

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
CPU3
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 4
Anmeldedatum: 17.12.12
Wohnort: Bremen
Version: ---
     Beitrag Verfasst am: 20.12.2012, 09:08     Titel:
  Antworten mit Zitat      
Hallo Jan,

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 Embarassed
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:

Code:
handles.timer = timer('TimerFcn', @(src,event)receive(src,event,hObject,handles) ,'BusyMode','Queue','ExecutionMode','FixedRate','Period',0.01);


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 habe ich das so abgeändert:

Code:
handles.timer = timer('TimerFcn', @(src,event)receive(src,event,hObject) ,'BusyMode','Queue','ExecutionMode','FixedRate','Period',0.01);


Und in der TimerFcn wie vorgeschlagen hinzugefügt

Code:
handles = guidata(hObject)


Nun läuft alles einwandfrei und ich habe endgültig verstanden, warum man sich die handles dynamisch holen sollte Rolling Eyes
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
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

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
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

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.