Verfasst am: 30.01.2016, 10:07
Titel: rekursiver Aufruf einer subgui
Hallo goMatlab Forum,
ich habe eine MainGUI u.a. mit 2 Pushbuttons, welche dieselbe Callback Funktion haben in der eine subgui aufgerufen wird. Die MainGUI ist zur Darstellung von 1 oder 2 Signalen und die Buttons für die Maximum und Minimum Peaks der Signale/des Signals.
Man drückt nun z.B. den Button Maximum Peaks und ruft damit die subgui auf. Die Peaks werden im Plotfenster dargestellt und die subgui zeigt in einer Tabelle die Peakwerte an (siehe Bild). Nun drückt der User den Button für die Minimum Peaks. D.h. die subgui wird erneut aufgerufen, während sie von dem ersten Call noch geöffnet ist. Somit werden nun auch die Min. Peaks sowohl im Plot als auch in der Tabelle der subgui angezeigt. Mein Problem liegt nun in der Durchführung der beiden Calls bzw. eigentlich mit der Weiterführung des 1. Calls nachdem der 2. Call beendet wurde.
Gibt es die Möglichkeit den 1. Call während des 2. Call zu beenden?
was genau meinst du mit "beenden"? Die Subgui schließen?
Wenn du beim Aufruf ein Handle auf die Subgui zurückholst und in der Hauptgui speicherst, kannst du die eine eventuell existierende Instanz von Subgui mit
close
oder
delete
schließen.
ishandle
ist hilfreich, um zu testen, ob die Subgui zuvor schon manuell geschlossen wurden.
Es gibt ja bei der Bedienung 2 Möglichkeiten zum Beenden der GUI. Entweder schließe ich die GUI über das x oder der Button.state = off. Sprich ich drück den Button Maxpaks zum Einschalten = 1. Call und Button.state = on. Nun drücke ich den Button nochmal zum Beenden = 2. Call und Button.state = off.
In diesem Fall werden zwar die Peaks im Plot gelöscht, aber die GUI bleibt immer noch offen.
Zitat:
Wenn du beim Aufruf ein Handle auf die Subgui zurückholst und in der Hauptgui speicherst, kannst du die eine eventuell existierende Instanz von Subgui mit close oder delete schließen. ishandle ist hilfreich, um zu testen, ob die Subgui zuvor schon manuell geschlossen wurden.
Ich kann den 2. Call nicht schließen, während der 1. Call in uiwait status hängt. Das geht zwar, aber komme ich dann zurück in den 1. Call ist von der subgui nichts mehr vorhanden. Ich erhalte dann folgenden Fehler:
Code:
Error using matlab.ui.Figure/set
Invalid or deleted object.
Error in PeaksTable (line214) set(handles.GUIPeaksTable,'Position',handles.PeaksTablePos)
Error in SignalViewer/FindPeaksItem_Callback (line4220)
PeaksTable(handles.graph, handles.Data.hLineS,...
Error using waitfor
Errorwhile evaluating ToggleTool ClickedCallback
Ich habe hier mal den Ablauf der subgui soweit gekürzt, so dass es nur um die Zustände subgui start, restart und close geht. Evtl. siehst du ja wo mein Fehler ist. Die Daten der subgui speichere ich im figure handle meiner Maingui.
Code:
function PeaksTable(axh, hLineS, hMainGUI, MinPeakDist, MinPeakHeight, PeaksNum, MaxPeaksState, MinPeaksState)
%% get Peaks and plot them --------------------------------------------------------------- % ... % ----------------------------------------------------------------------------------------
if(sum(ishghandle(handles.hLineMaxPeaksS)) > 0) || (sum(ishghandle(handles.hLineMinPeaksS)) > 0) % grafic handle available % show Max and/or Minpeaks in table else % NO peaks available -> grafic handle empty % save subgui data in MainGUI setappdata(hMainGUI,'hPeaksTable',handles) % close GUI
%close_GUI
end
% get current gui position
handles.PeaksTablePos = get(handles.GUIPeaksTable,'Position');
% delete data cursor in plot delete(findall(0,'type','line','Tag','PeakMarker')) delete(findall(0,'Tag','PeakLabel'))
% get current gui position
handles.PeaksTablePos = get(handles.GUIPeaksTable,'Position');
for m = 1:sum(ishghandle(handles.hLineMaxPeaksS)) % delete max peaks in existing plot delete(handles.hLineMaxPeaksS(m));
delete(findall(0,'type','line','tag',['hLineMinPeaksS' num2str(m)]))
handles.hLineMaxPeaksS(m) = gobjects(1);
end
for m = 1:sum(ishghandle(handles.hLineMinPeaksS)) % delete min peaks in existing plot delete(handles.hLineMinPeaksS(m));
delete(findall(0,'type','line','tag',['hLineMinPeaksS' num2str(m)]))
handles.hLineMinPeaksS(m) = gobjects(1);
end
% save the changes to the structure guidata(gcbo,handles);
% save subgui data in MainGUI setappdata(hMainGUI,'hPeaksTable',handles) % close GUI delete(handles.GUIPeaksTable)
Ich gehe mal von einem Signal aus und es erfolgt folgender Ablauf
1. Button MaxPeaks on = von User gedrückt
- Plot MaxPeaks und zeige MaxPeak-Werte in Tabelle
1. Call der subgui
2. Button MinPeaks on
- Plot Max und MinPeaks und zeige Peakwerte in Tabelle
2. Call der subgui -> 1. Call ist noch aktiv wegen uiwait
entweder
3a. subgui wird geschlossen (x angeklickt)
- schließe die subgui und lösche existierte Peaks im Plot -> ENDE
oder
3b. Button MinPeaks off
- lösche die Minpeaks im Plot und in der Tabelle und zeige nur die MaxPeaks
4. Button MaxPeaks off
- schließe die subgui und lösche die MaxPeaks im Plot -> ENDE
Mein Problem ist der noch offne 1.Call, während ein 2. Call gerade beendet wurde. Daher fragte ich auch, ob man im 2. Call den 1. Call einfach beenden kann. close oder delete schließen nur den aktuellen call und logischerweise wird dann der vorhergehende Call bei Rekursion weitergeführt.
Ich habe nun zwar den Ablauf wie gewünscht hinbekommen. aber nachdem die CloseRequestFcn @close_GUI ausgeführt wurde, ist der 2. Call beendet und nun lande ich wieder beim 1. Call und habe wieder folgender Fehler, da die figure in der close Funktion ja schon gelöscht wurde.
Ich habe es auch mit einem uiresume(handles.GUIPeaksTable) in der Close Fcn versucht, was aber nichts bewirkt.
Aber vermutlich wirst du auch mit dieser Beschreibung deine Probleme haben sie nachzuvollziehen. Das Projekt ist mittlerweile schon recht groß, weshalb es mir schwer fällt diese Thematik auf ein eigenes lauffähiges Bsp. zu bringen. Ich kann dir natürlich das Projekt geben...aber dann brauchst du auch eine Anleitung, was wie zu bedienen ist und wo breakpoints zu setzen sind. Ist halt auch nicht ideal.
Dennoch vielen Dank für deine Bemühung mir zu helfen.
Ich habe jetzt noch einen Versuch ohne das uiwait(subgui) gemacht. Damit erreiche ich ja, dass nach der Abarbeitung des Codes in der subgui, wieder in die Callback der MainGUI gesprungen wird.
Ich habe damit den gewünschten Ablauf herstellen können. Bis auf eine Sache...klickt man das x zum Schließen der subgui an, springt er nicht mehr in die Callback der MainGUI zurück? Warum nicht?
Wenn ich nämlich die subgui darüber schließe, bleibt der Button state auf on, wenn er zuvor gedrückt wurde. Da ich dann nicht mehr in der Callback der Maingui zu dem Button lande, kann ich auch den state nicht auf off setzen.
Die Peaks und die subgui sind zwar weg, aber ein oder beide Button(s) ist/sind an
klar...du hast Recht! Der Code in der subgui wurde ja durchgeführt, dann zurück in den Callback der MainGUI. Dort wird noch Code abgefragt aber nicht ausgefüht und die Callback wird verlassen. Erst dann drückt man auf x und die subgui wird geschlossen.
Sicherlich ist es kein Problem die Buttons in der subgui auszuschalten. Aber das ist schon irgendwie von hinten durch die Brust ins Auge. Es muss doch auch einen Weg über uiwait in der subgui geben. Dann ist auch das Umschalten der Button states kein Problem. Oder man nutzt eine Togglebutton, der nach dem Betätigen sofort wieder auf off geht. Dann sieht man aber an Hand der Buttons nicht, welche Peaks an sind. Was ich auch nicht verstehe, ist die Sache mit den geplotten Peaks. Werden Min- und MaxPeaks angezeigt, wurde die subgui 2 mal aufgerufen. Die Peaks vom 1+2.Call können mit
Code:
% Line Handles der Peaks löschen delete(handles.hLineMaxPeaksS) delete(handles.hLineMinPeaksS)
entfernt werden. Sind beide Peaks an und werden nacheinander durch beide Buttons entfernt wird die subgui am Ende geschlossen. Also also ok. Sind beide Peaks an, aber die subgui wird durch x beendet, werden immer die Max- oder MinPeaks, die im 1. Call aufgerufen wurden, nicht gelöscht. Obwohl die line handles beider Peaks in der close function vorhanden sind.
Dann können beide Peaks nur über findobj gelöscht werden.
Code:
% delete Max Peaks for m = 1:sum(ishghandle(handles.hLineMaxPeaksS)) % delete max peaks in existing plot delete(findobj(0,'type','line','tag',['hLineMaxPeaksS' num2str(m)]))
handles.hLineMaxPeaksS(m) = gobjects(1);
end
Ich weiß nun warum das Löschen des handles aus dem ersten Call nicht mehr direkt über das Objekt handle geht.
Im 1. Call wird ja entweder Min oder Max Peaks angeklickt und somit das 1. Objekt handle erzeugt. Beim 2 Call sind nun Min und Max Peaks ausgewählt und somit werden die Objekt handles für beide Peaks neu erzeugt. Dadurch sind diese beiden handles andere als das handle aus dem 1. Call.
Der Zugriff auf das Objekt handle aus dem 1. Call ist somit nur über findobj zu realisieren.
Ich müsste daher immer gleich beide Peaks erzeugen und nur jenen sichtbar machen, der gerade ausgewählt wird. Dann könnte ich mit den handles arbeiten. Da dieser Programmablauf aber andere Probleme mit sich bringt, bleibt es bei der Umsetzung mit findobj.
Gruß DSP
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.