How to modify the handles structure (GUI) from an external function

Hi,
I am developing a GUI. I can modify the handles structure (for example handles.variable1 = 2) within callbacks. However I am not able to do the same within an external function. E.g., this does not work:
function [matrix, indexVector] = myFunction(handles)
handles.variable1 = 1;
It is important to note that myFunction does not belong to the GUI callbacks, it is simply a function I have created in another m file. When I call it I can read the handles struture (actually im passing them as a parameter) but when I try to modify them the modification is not recorded.
Best,
-MRR

 Réponse acceptée

Sean de Wolski
Sean de Wolski le 8 Mar 2013
Modifié(e) : Sean de Wolski le 8 Mar 2013
function [matrix, indexVector] = myFunction(handles)
handles.variable1 = 1;
guidata(handles.figure1,handles)
Where figure1 is the 'Tag' of the figure. You want to make sure that you assign the handles structure to the right place (i.e. the figure). hObject is dynamic, handles will always have the field for the figure.

10 commentaires

Seems logic to me, but figure1 is the tag associated to the main figure of the gui. The handles structure is not saved there.
You bet it is!
In the figure's openingfcn etc. hObject will be the figure!
MRR
MRR le 14 Mar 2013
Modifié(e) : MRR le 14 Mar 2013
I am doing this:
function OpeningFcn(hObject, ~, handles, varargin)
...
handles.D = myFunction(hObject, handles);
and inside myFunction(hObject,handles)
handles.variable1 = 1;
guidata(handles.figure1,handles);
Then, when the program comes back to the OpeningFcn if I debug try to access to variable1:
handles.variable1
I got the error: Reference to non-existent field 'variable1'.
Error in OpeningFcn (line 170) handles.variable1
I get the same error if I do guidata(hObject, handles).
PS: myFunction is in another .m file, as I said in the main post.
PS2: I modified myFunction to pass hObject. Originally I just passed the handles structure.
MRR
MRR le 14 Mar 2013
Modifié(e) : MRR le 14 Mar 2013
Even If previously create handles.variable1 = [ ] in the OpeningFcn, it is not updated, and when returning from myFunction it has still the value [ ] instead of 1 (the value assigned inside myFuncion)
In the openingfcn the figure doesn't exist yet so that's why it's empty (and called the "open"ing function. Do the above in the outputfcn
MRR
MRR le 19 Mar 2013
Modifié(e) : MRR le 19 Mar 2013
Sean, thanks for your answer, but still, that does not work.The point is that the external function does not modify the value of an already created variable from the handles structure and that is what I am trying to do, with no sucess.
Doing the above in the outputfcn does not solve my problem, since, as I said in the main post I am trying to modify the handles structure from an external funcion.
I could of course return all the handles structure from the function but that I think that is a not very good solution.
@MRR: The methods posted by Sean and Azzi do solve the problem already: The modified struct handles is stored in the ApplicationData of the figure by guidata. There is no better way to do this, because this does work reliably from an external function also. If you still insist, that this does not work, I'm convinced, that your test is wrong. Perhaps you are using a handles struct, which existed during the creation of the GUI, and not the updated versions: See FAQ: Incomplete handles struct
MRR
MRR le 19 Mar 2013
Modifié(e) : MRR le 19 Mar 2013
@Jan Simon: Again, thank you for your answer. I am going to detail my tests: I have created a variable called "variable1" in the OpeningFcn:
function myguide_OpeningFcn(hObject, ~, handles, varargin)
%some code here...
handles.variable1 = 1;
guidata(hObject, handles);
%....
1. When it works: Let's say I have created my gui with GUIDE and I have a button called "Simulate". Then I do the following:
function errorParameters = Simulate_Callback(hObject, eventdata, handles)
%some code here ...
handles.variable1 = handles.variable1 + 1;
guidata(hObject, handles);
I can debug and see how handles.variable1 is increased by one, each time I push the simulate button in the gui. So far, it works as expected.
2. When it does not work: If my Simulate_Callback calls also another function:
function errorParameters = Simulate_Callback(hObject, eventdata, handles)
%some code here ...
[output1, output2] = myFunction(hObject, handles);
handles.variable1 = handles.variable1 + 1;
guidata(hObject, handles);
And inside myFunction(hObject, handles) I do:
handles.variable1 = 200; %or any other value
guidata(hObject, handles);
Then, handles.variable1 takes the value 200 while the program is inside the scope of myFunction. However, when myFunction returns I can notice (when debugging) that the handles.variable1 has not been modified and whatever I do inside myFunction with variable has no effect when returning.
I have checked it several times and the behaviour is the same. Actually I have copied myFunction in the same .m file than the Guide, with same results.
Best,
-MRR
Jan
Jan le 20 Mar 2013
Modifié(e) : Jan le 20 Mar 2013
@MRR: Yes, of course, this is the expected behavior. Inside myFunction you update the handles struct and store it in the figure afterwards. Then after returned to Simulate_Callback, you use the local copy of handles with its value before calling myFunction() and overwrite the changes from inside this function. A suggestion for improvements:
function errorParameters = Simulate_Callback(hObject, eventdata, handles)
%some code here ...
handles = guidata(hObject); % Care for the newest version explicitly!
[output1, output2] = myFunction(hObject, handles);
handles = guidata(hObject); % Get the version updated in myFunction!
handles.variable1 = handles.variable1 + 1;
guidata(hObject, handles);
And inside myFunction(hObject, handles) I do:
handles.variable1 = 200; %or any other value
guidata(hObject, handles);
So Azzi's and Sean's answers hit the point already, but in your code there was a problem at another location, namely in the caller, which forgot to obtain the updated struct.
@Jan Simon: Thank you, now it works. The key instruction that makes the handles structure to be updated is (and as you can see it wasnt used in any other previous solution in this post):
handles = guidata(hObject); % Get the version updated in myFunction!
But bear in mind that the other solutions (mine included) did not work, i.e., using guidata(hObject, handles) does not update the handles structure modified by myFunction, however it works for any callback function defined in the gui (i.e, those functions that are automatically associated with the pushbuttons, etc..), so Azzi's and Sean's answers, although hit the point, do not work. Of course, their and your feedback is very appreciated.
All in all, I would say the way GUIDE manages the handles structure is confusing.
Hope this discussion will help another "gui developers"
Best and thank you!
-MRR

Connectez-vous pour commenter.

Plus de réponses (3)

Use
function [matrix, indexVector] = myFunction(hObject,handles)
handles.variable1 = 1;
guidata(hObject,handles)

4 commentaires

MRR
MRR le 14 Mar 2013
Modifié(e) : MRR le 19 Mar 2013
I try to do that but the variable1 is not saved when I try to access it inside the GUIDE (and outside myFunction). However, when I do this in a callback (e.g. the callback from a pushbutton), it works.
@MRR: I disagree: The shown code does save the modified struct handles in the GUI, as long as you provide a handle of any object inside the GUI as hObject. So please explain with details, why you assume, that this method does not work and see my comment to Sean's answer.
Thanks Jan Simon. Detailed in Sean's answer is my explanation.
MRR, if so then accept his answer

Connectez-vous pour commenter.

handles = guihandles(gcbo); % if not presents in the other external function

Catégories

En savoir plus sur Interactive Control and Callbacks dans Centre d'aide et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by