Verfasst am: 04.11.2008, 11:08
Titel: Wie verbinde ich eine GUI mit einem Skript?
Hallo
ich möchte folgendes hinbekommen:
In einer GUI lese ich durch Textfelder Werte ein.
Je nach dem welcher Button dann gedrückt wird, werden die Werte unterschiedlich berechnet.
Die Funktionen, die die Berechnung ausführen sind jeweils in m-files gespeichert.
Meine Architektur sieht so aus:
Skript (ein m-file halt), welches Initialisierungen vornimmt und die GUI startet.
Im Skript soll dann entschieden werden: Ist Button 1 gerdück, mache das, ist Button 2 gedrück mache was anderes, usw
Die Architektur desswegen, weil das ganze noch sehr viel größer werden soll (also viele Funktionen, viele Buttons,....)
Und jetzt hörts auch schon auf:
Wie kann ich denn überhaupt einen Code schreiben, der forlaufend prüft, ob in der GUI ein Button gedrück ist oder nicht, und dann die passende Funktion aufruft?
Weil wenn ich im Skript schreibe
h = findall(0,'type','figure','Name','test_interface')
handles = guidata(h)
if get(handles.button,'Value') % Value == 1: Button Pressed
g = test_fun(1000,300,0,1,3,1,ne); %Fuktion für die Berechnung
erg = solve(g,'ne');
set(handles.result,'String','erg');
end
Dieser Code lüft mit dem Aufrufen des Skrips einmal durch.
Dabei ist der Button noch nicht gedrückt.
Somit passiert nichts.
Eine Endlosschleife um die Abfrage herum ist sicher schlecht.
Ich weiß dass das sicher mit diesen ominösen "Callback" gehen muss.
Ich habe schon viel über Kommunikation zwischen GUIs gelesen, aber ich kann das hier nicht umsetzen, ich habe ja nur eine GUI. Da bringt es auch nichts Daten über handles zwischen GUIs auszutauschen.
Ich muss dazusagen, dass ich noch nicht ganz durchgestiegen bin, bzw umsetzen kann, was callbacks sind/tun.
richtig. Die Lösung heisst Callbacks. Es gibt bereits einige Beiträge hier, die genau dies thematisieren. Ganz kurz erklärt:
Callbacks werden immer dann aufgerufen, wenn Objekt ein Event verschicken. Zum Beispiel beim Verschieben von einem Fenster, oder auch beim Drücken des "x" des Fensters. So liefert
u.a. auch CloseRequestFcn = closereq für das aktuelle Fenster.
Eine Callback-Funktion hat standardmäßig immer 2 Eingabewerte (hObject, eventdata), zum einen ein Handle auf das Objekt, das gerade ein Event verschickt hat (gedrückt - verschoben - bedient - editiert usw. wurde), und ein Feld mit zusätzlichen Daten (sind öfters leer). Man kann der Callback-Funktion natürlich auch mehr Werte übergeben.
Auf die Art und Weise werden Callback-Funktionen definiert. Du kannst der Funktion natürlich auch Variablen übergeben, allerdings wird dann nur der Inhalt bei der Zuweisung übergeben (kein Pointer!). Ein eleganter Weg, dies zu umgehen, bietet
Jedoch kann ich diese Geschichte immer noch nicht umsetzten
Das kann doch nicht so schwer sein!?
z.B. sieht mein Script so aus:
Code:
...
test_interface; % Interface, also GUI Starten
...
% geht so nicht: % abfragen wies um den guten Button steht: ifget(handles.button,'Value')% Value == 1: Button Pressed
tu was...
else
tu was anderes...
end
% --- Executes on button press in button. function button_Callback(hObject, eventdata, handles) % hObject handle to button (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA)
isPushed = get(hObject, 'Value')
Wie kann ich denn oben "in Echtzeit" abfragen, wie der Zustand des Buttons ist?
get(handles.button,'Value') wird ja beim ersten aufrufen des Scrips ausgewertet und dann nie wieder. Ich müsste also wieder an diese Abfrage springen.
Also Button und Script sollen parallel laufen.
Geht das überhaupt?
Ich verstehe einfach nicht wie genau die Funktionen ausgeführt werden, weil ich müsste in meinem Script ja an der Stelle mit der If-Abfrage irgendwie mitbekommen, wann sich der Button bewegt hat.
Also die muss sozusagen immer überprüft werden.
Verstehtst Du was ich meine?
Und eine Endlosschleife ist schlecht, darum soll da irgendwie ein callback rein...?!
Ich kann das leider nicht besser ausdrücken.
hab das gleiche prob. schreibe momentan alles in das m-file was von der GUI automatisch erstellt wurde. Hab 3 axes-felder erstellt und will dort 2 bilder und einen livestream rein haben. 1 bild hab ich schon drin.
schreib ich das in die m-file-datei der gui dann gehts.
Code:
axes(handles.axes1); % Auswahl des entsprechenden Axes-Objekts
G1=imread('cam7.png'); % Einlesen der Grafik imshow(G1); % Grafik ausgeben, axisimage; %Grafik entzerren
axis off % Koordinatenachsen ausblenden
du verstehst da glaub ich etwas falsch (oder ich). Ich meine verstanden zu haben, dass du immer dann, wenn ein bestimmter Knopf gedrückt wird, eine bestimmte Aktion (Funktion, Skript) ausgeführt werden soll.
Die Funktion button_Callback(hObject, eventdata, handles) wird immer dann ausgeführt, wenn der betreffende Button (bzw. das Objekt) gedrückt wird (so steht es ja auch in der Kommentarzeile darüber). Die Zeile mit "isPushed" ist eigentlich überflüssig.
Ich versuche dir hier nun ein Minimalbeispiel darzulegen:
Code:
function main
% GUI erstellen
fg = figure;
% Pushbutton rein
hPushbutton = uicontrol('Style','PushButton','String','PUSH ME');
% Callback zuweisen set(hPushbutton, 'Callback', @cb_pushbutton);
return
% Callback Funktion definieren! function cb_pushbutton (hObject, eventdata) disp('Pushbutton wurde gedrückt!!!');
return
Nun sollte - einmal "main" aufgerufen, immer dann wenn du den Knopf "PUSH ME" drückst, auch "Pushbutton wurde gedrückt" erscheinen (im MATLAB Command Window). Die Funktion "cb_pushbutton" wird immer dann - und nur dann - ausgeführt, falls dieser Knopf gedrückt wird. Die Überprüfung ob der Knopf gerade gedrückt wird, ist damit überflüssig!!
die Struktur "handles" ist in GUIDE dazu da, dass man auch andere Objekte "sehen" kann. Stell dir vor, du willst durch einen Knopfdruckes des Knopfes "meinButton" auslösen, dass in die Achse "meineAchse" irgendwas gemalt wird. Dann hast du in deiner Callback-Funktion das Problem, dass du "meineAchse" gar nicht kennst. GUIDE erschlägt dieses Problem, indem es allen Callback-Funktionen die Struktur "handles" mitgibt, das alle (oder fast alle) Handles (sowas wie Zeiger) auf die Objekte beinhaltet.
In deinem Fall scheinst du diese Variable nicht zu übergeben bzw. lässt dein Codebeispiel nicht erahnen was es gerade tut bzw. wo es sich befindet. Ein bisschen mehr Code wäre daher wünschenswert.
functionvarargout = liveImg_Pic(varargin) % LIVEIMG_PIC M-file for liveImg_Pic.fig % LIVEIMG_PIC, by itself, creates a new LIVEIMG_PIC or raises the existing % singleton*.
%
% H = LIVEIMG_PIC returns the handle to a new LIVEIMG_PIC or the handle to % the existing singleton*.
%
% LIVEIMG_PIC('CALLBACK',hObject,eventData,handles,...) calls the local % function named CALLBACK in LIVEIMG_PIC.M with the given input arguments.
%
% LIVEIMG_PIC('Property','Value',...) creates a new LIVEIMG_PIC or raises the % existing singleton*. Starting from the left, property value pairs are % applied to the GUI before liveImg_Pic_OpeningFunction gets called. An % unrecognized property name or invalid value makes property application % stop. All inputs are passed to liveImg_Pic_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one % instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Copyright 2002-2003 The MathWorks, Inc.
% Edit the above text to modify the response to help liveImg_Pic
% Last Modified by GUIDE v2.5 04-Nov-2008 11:20:47
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @liveImg_Pic_OpeningFcn, ...
'gui_OutputFcn', @liveImg_Pic_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
ifnargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
% --- Executes just before liveImg_Pic is made visible. function liveImg_Pic_OpeningFcn(hObject, eventdata, handles, varargin) % This function has no output args, see OutputFcn. % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % varargin command line arguments to liveImg_Pic (see VARARGIN)
% Choose default command line output for liveImg_Pic
handles.output = hObject;
% UIWAIT makes liveImg_Pic wait for user response (see UIRESUME) % uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line. functionvarargout = liveImg_Pic_OutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT); % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure varargout{1} = handles.output;
% Grafik1 einfügen axes(handles.axes1); % Auswahl des entsprechenden Axes-Objekts
G1=imread('cam7.png'); % Einlesen der Grafik imshow(G1); % Grafik ausgeben, axisimage; %Grafik entzerren
axis off % Koordinatenachsen ausblenden
dieser Teil wird ohne prob ausgeführt. Heißt es wird ein Bild im Axes1 angezeigt. Ich will aber eigentlich das dieses Stück code in meinem m-file steht. also hab ich versucht ein weiteres Bild in das zweite Axes zu bekommen.
ich hab keine ahung wie ich mit hilfe der handles sagen kann nimm das zweite bild und zeig das im zweiten axes an. bei mir kommt nur die fehlermeldung: ?? Undefined function or variable "handles"
wie müsste ich das richtig schreiben das die GUI weiß was se zu tun hat?
Das sollte dir die handles auf die Objekte der GUI liefern. Allerdings sehe ich hier nirgends, dass eine zweite Achse (handles.axes2) erstellt wird. Falls du die noch nicht erstellt hast, kannst du die mit
erstellen, bzw. halt dann angepasst an deine Bedürfnisse.
Irgendwie ist mir das alles noch ein bisschen unklar: Du erzeugst eine GUI mit einer Achse und schreibst zum Zeitpunkt, wo Werte zurückgegeben werden, ein Bild in diese Achse. Nun willst du in eine zweite Achse ebenfalls etwas reinschreiben. Diese zweite Achse existiert allerdings nirgends.
Dann wiederum holst du dir Daten von irgend einem Gerät (nehme ich mal an). Die GUI wird nun ein zweites mal erzeugt (in einem anderen Fenster), das erste Bild wird wieder angezeigt und mit dem Bild vom Gerät überschrieben.
Irgendwie ist das für mich ein kleines WirrWarr. Wennn ich das richtig verstanden habe, willst du eine GUI erstellen, die 2 starre Bilder und ein sich änderndes Bild, das von einem anderen Gerät kommt, enthält. Dann würde ich es so machen, dass ich in der GUI diese zwei Bilder in die Achsen lade (in der liveImg_Pic_OpeningFcn!!) und dann in meiner Main-Funktion das Bild in der dritten Achse aktualisiere - in der Form
Hallo Kalle,
du verstehst da glaub ich etwas falsch
Stimmt
Was ich ursprünglich machen wollte, geht wohl gar nicht.
Ich habe jetzt eine Lösung gefunden.
Was ich machen will, ist eben die GUI "sauber" zu halten, also dass diese wirklich nur eine Maske ist und keinen zusätzlichen Code hat oder irgend was berechnet.
Das mache ich so, dass ich, wenn eine Callbackfunktion in der GUI ausgelöst wird (durch nen Button oder ein Menü) an dieser Stelle immer wieder das gleiche Skript aufgerufen wird.
Code:
% --- Executes on button press in pushbutton_TE. function pushbutton_TE_Callback(hObject, eventdata, handles) % hObject handle to pushbutton_TE (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA)
action;
In dem Skript lese ich dann die handles aus und reagiere darauf.
Also z.B.
if "Button 1 Gerück", öffne Funktion1.
if "Menüauswahl 4", plot(so und so)....
Code:
% script action
% get handles
h = findall(0,'type','figure','Name','interface');
handles = guidata(h)
nunja, ich würde das anders machen. Die Logik muss ja auch nicht in deiner GUI stehen. So ist es halt umständlich weil du immer alle GUI-Elemente abfragen musst ob die gerade was gemacht haben. Außerdem ist das wohl nicht der Sinn der Callback-Funktion, weil du ja eigentlich weisst welcher Knopf gerade gedrückt worden ist, du aber trotzdem nochmal bei allen Elementen abfragst.
Du kannst es ja sochen machen:
Jede Callback-Funktion erhält ihr eigenes Skript. z.B.
Code:
function pushbutton_TE_Callback(hObject, eventdata, handles)
action_TE;
return
function pushbutton_TX_Callback(hObject, eventdata, handles)
action_TX;
return
function slider_Callback(hObject, eventdata, handles)
action_slider;
return
usw.
Oder aber du verwendest Funktionen anstelle von Skripts. Die haben den Nachteil (oder Vorteil - wie mans nimmt), dass Variablen und Werte NICHT in den Workspace geladen werden (bzw. nicht in den "base" Workspace). Dafür können sie aber Eingabeargumente erhalten. z.B.
Code:
function pushbutton_TE_Callback(hObject, eventdata, handles)
action('TE');
return
function pushbutton_TX_Callback(hObject, eventdata, handles)
action('TX');
return
function slider_Callback(hObject, eventdata, handles)
action('slider');
return
ich würde gerne nach drücken eines knopfes auf der GUI alle Werte meiner 6 Slider an meine eigene Funktion myfunc (a,b,c,d,e,f) übergeben und ausführen lassen.
aber folgendes klappt nicht:
get (handles.slider_1,'Value') % gibt nichtmal den Wert hinterm slider zurück.
Das, was mich irretieren ließ, war, dass ich diesen Befehl nicht aus dem Command-Window starten konnte. Klar, weil im Workspace ist ja nichts zu sehen. Aber warum? Warum kann ich meine Handles, wie bspw. "handles.slider_1" nicht im workspace sehen?
Gibts eine Möglichkeit, Werte von Handles anzuzeigen?
a) Ich wollte eigentlich auf Variablen zugreifen, die ich in einer Funktion erstelle, und nicht auf Eingabeparameter.
b) Was ist denn der Unterschied zwischen findall und "get" ?
Habe bisher versucht mit get(handles, 'Value') Werte zu bekommen.
c) alles in Allem suche ich verzweifelt Antworten auf diese Fragen, damit ich mein Programm hier zum Laufen kriege. Vergeblich: Kann den eingelesenen Dateinamen nicht aus einer Funktion in die andere übergeben. Warum?
Code:
% --- Executes on button press in pushbutton_play. function pushbutton_play_Callback(hObject, eventdata, handles) % hObject handle to pushbutton_play (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA)
% --- Executes on button press in pushbutton_load. function pushbutton_load_Callback(hObject, eventdata, handles) % hObject handle to pushbutton_load (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA)
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.