why when i use two guides i'm losing the handles variables?

function solicita_espacios(hObject, eventdata, handles)
if get(handles.checkbox1,'Value')==1% si el checkbox de materia gris es seleccionado
%en esta parte se pide al usuario que defina el espacio a trabajar de
%acuerdo a la cantidad que definió
%if (handles.Mgris)
Cespacios=str2double(get(handles.edit6,'String')); %cantidad de espacios nativo,normalizado etc.
for ce=1:Cespacios
opciones={'ninguno','espacio nativo','sin modular normalizado','modulado normalizado','nativo+sin modular normalizado','nativo+modulado normalizado','nativo+modulado+sin modular','modulado+sin modular normalizado'};
[s,v] = listdlg('PromptString','Seleccione un mapa:',...
'SelectionMode','single',...
'ListString',opciones)
switch (s)
case 1
espacio=[0 0 0];
case 2
espacio=[0 0 1];
case 3
espacio=[0 1 0];
case 4
espacio=[1 0 0];
case 5
espacio=[0 1 1];
case 6
espacio=[1 0 1];
case 7
espacio=[1 1 1];
case 8
espacio=[1 1 0];
end
EspacioMgris{1,ce}= espacio;
handles.EspacioMgris=EspacioMgris;
guidata(hObject, handles)
end
handles = guidata(hObject);
end
if get(handles.checkbox2,'Value')==1% si el checkbox de materia blanca es seleccionado
%en esta parte se pide al usuario que defina el espacio a trabajar de
%acuerdo a la cantidad que definió
Cespacios=str2double(get(handles.edit6,'String')); %cantidad de espacios nativo,normalizado etc.
for ce=1:Cespacios
opciones={'ninguno','espacio nativo','sin modular normalizado','modulado normalizado','nativo+sin modular normalizado','nativo+modulado normalizado','nativo+modulado+sin modular','modulado+sin modular normalizado'};
[s,v] = listdlg('PromptString','Seleccione un mapa:',...
'SelectionMode','single',...
'ListString',opciones)
switch (s)
case 1
espacio=[0 0 0];
case 2
espacio=[0 0 1];
case 3
espacio=[0 1 0];
case 4
espacio=[1 0 0];
case 5
espacio=[0 1 1];
case 6
espacio=[1 0 1];
case 7
espacio=[1 1 1];
case 8
espacio=[1 1 0];
end
EspacioMblanca{1,ce}= espacio;
handles.EspacioMblanca=EspacioMblanca;
guidata(hObject, handles)
end
handles = guidata(hObject);
end
if get(handles.checkbox3,'Value')==1 % si el checkbox de liquido cefalorraquideo es seleccionado
%en esta parte se pide al usuario que defina el espacio a trabajar de
%acuerdo a la cantidad que definió
Cespacios=str2double(get(handles.edit6,'String')); %cantidad de espacios nativo,normalizado etc.
for ce=1:Cespacios
opciones={'ninguno','espacio nativo','sin modular normalizado','modulado normalizado','nativo+sin modular normalizado','nativo+modulado normalizado','nativo+modulado+sin modular','modulado+sin modular normalizado'};
[s,v] = listdlg('PromptString','Seleccione un mapa:',...
'SelectionMode','single',...
'ListString',opciones)
switch (s)
case 1
espacio=[0 0 0];
case 2
espacio=[0 0 1];
case 3
espacio=[0 1 0];
case 4
espacio=[1 0 0];
case 5
espacio=[0 1 1];
case 6
espacio=[1 0 1];
case 7
espacio=[1 1 1];
case 8
espacio=[1 1 0];
end
EspacioLiquido{1,ce}= espacio;
handles.EspacioLiquido=EspacioLiquido;
end
handles = guidata(hObject);
end

 Risposta accettata

You included a lot of code in your question. In the future, please just attach the m files to your question using the paperclip button. As well, please describe how you are using your two GUIs. Does one launch the other, do they both run at the same time, etc.
So you have two GUIs that "communicate" information between each other using global variables. (There are alternatives to this. You can store the data in the handles object of one GUI, and then access that handles data from the other. See how do you access one GUI from another for details.) You are then finding that the handles.EspacioMgris does not exist...but you don't say where this is failing, only that it isn't there when you enter the solicita_espacios function, which is called from the pushbutton1_Callback of your "bigger" GUI (not the menus one). Taking a look at this callback we see that your code
  • declares several global variables (that is fine, though you may want to explore the alternative already described)
  • sets a variable named x to be the handle of the edit3 control (suspicious...)
  • iterates over x, prompting the user for information
  • calls the function solicita_espacios (where you comment on the problem)
  • do some other stuff
  • again start iterating over x (??) and make use of handles.EspacioMgris in the inner loop (note that you set three global variables to the same handles.EspacioMgris{1,1} value)
  • does more stuff
So let us first look at the assignment of x
x=handles.edit3;
for vgauss=1:x
% etc.
This seems strange because the handle to a control/widget (in your case, the edit box named edit3) is (almost always) a positive non-integer, so of the form 179.34343321. So why would you want to iterate over this value? This doesn't seem correct (and isn't) but is explained in the callback to edit3
function edit3_Callback(hObject, eventdata, handles)
Val=get(hObject,'String');
NewVal = str2double(Val);
handles.edit3=NewVal;
guidata(hObject, handles);
So once the user has finished typing data into edit3, this callback fires and the code immediately grabs the string data from edit3, converts it to a number and then OVERWRITES the handle for edit3 with that number (saving it using guidata). This is WRONG. The handles structure manages all the handles (or unique identifiers) to all widgets/controls on your GUI, and all user-defined data (so these are the things that you add to it). The control identifiers (handles) are maintained in this structure so that your code can access the information stored in one control from the (say) callback of another. By overwriting this data, you are preventing other control callbacks from accessing this data. Note that in this callback, the value for hObject s the same as the value for handles.edit3.
You need to remove the edit3_Callback and all other similar callbacks for your other edit controls. Then, your code in the pushbutton1_Callback would change from
x=handles.edit3;
for vgauss=1:x
% etc.
to
x=str2double(get(handles.edit3,'String'));
for vgauss=1:x
% etc.
So we have really taken the body of your callback and re-used it here.
Now, if we look at the solicita_espacios function we see that it does
function solicita_espacios(hObject, eventdata, handles)
if (handles.Mgris)==1
Cespacios=handles.edit6;
for ce=1:Cespacios
opciones={'ninguno','espacio nativo',...};
[s,v] = listdlg('PromptString','Seleccione un mapa:',...
'SelectionMode','single',...
'ListString',opciones)
switch (s)
case 1
espacio=[0 0 0];
case 2
% etc.
end
EspacioMgris{1,ce}= espacio;
handles.EspacioMgris=EspacioMgris;
guidata(hObject, handles)
end
end
% then another if block
So it enters the if body if the condition (handles.Mgris)==1. As before, you don't see to save the results stored in your controls (in this case a checkbox) to other fields within handles. Just access this data directly as
if get(handles.checkbox1,'Value')==1
So once in the body, we again iterate over some value from edit6. The code
Cespacios=handles.edit6; %cantidad de espacios nativo,normalizado etc.
for ce=1:Cespacios
should be replaced with
Cespacios=str2double(get(handles.edit6,'String'));
for ce=1:Cespacios
and the callback for edit6 deleted.
Back to the code, the user is prompted with options for a number of times, and after each prompt the data is saved to the handles.EspacioMgris field, and guidata is called. Doing this repeatedly (on each iteration of the loop) is unnecessary, and so the two line
handles.EspacioMgris=EspacioMgris;
guidata(hObject, handles);
should be moved outside of the for loop, so that it just occurs the once.
Now that we've done the above for the grey (?) checkbox, the code does the same for a couple of other checkboxes.
Once we exit the solicita_espacios function, we are back in the pushbutton1_Callback and do start a couple of loops (again, fix the y=handles.edit4) and do
spaceWMG1=(handles.EspacioMgris{1,1});
spaceGMG1=(handles.EspacioMgris{1,1});
spaceLCG1=(handles.EspacioMgris{1,1});
Note that handles is a copy of the structure BEFORE the code entered the solicita_espacios function, so it won't have the updated data. You will need have either your solicita_espacios function return the handles structure as
handles = solicita_espacios(hObject, eventdata, handles);
and probably do the same for solicita_mapas, or just do
solicita_espacios(hObject, eventdata, handles);
handles = guidata(hObject);
I'm not sure if that really answers your question, but it does give you a couple of things to think about. Presumably you are initializing handles.EspacioMgris in your Opening_Fcn of the GUI to handle the case where the grey checkbox isn't checked.

10 Commenti

hi, thank you for your corrections, let me explain a little bit about the code: the target is process two directory images, for do that the user has to input how many Gauss values, maps and spaces.
in this moment my problem is when i use a function, for example solicita_espacios, following your suggestion i use
handles = guidata(hObject);
but when finished the function im still losing the variable EspacioMgris.
on the other hand, i use the variable x because i need to know how many parameters need the user to iterate.
handles.EspacioMgris is three times, yes you right, in this moment is just to test the script whit the job, but i will should change.
i loaded the .m to be more easy.
The handles = guidata(hObject); should not be in the solicita_espacios function but outside of it. Here is your order of functions
  • pushbutton1_Callback is called
  • pushbutton1_Callback calls solicita_espacios
  • pushbutton1_Callback calls solicita_mapas
  • pushbutton1_Callback starts to iterate and use handles.EspacioMgris
In your code, as it stands now, when pushbutton1_Callback it has a copy of the handles structure, call it "copy A". solicita_espacios is called and is passed the "copy A" handles structure. This function updates the handles structure, creating "copy B", and saves this updated handles with the usual guidata(hObject,handles). The function exits, and returns to pushbutton1_Callback, where the handles structure is "copy A"...so is not the updated "copy B". The code then calls solicita_mapas with the "copy A" handles structure which updates a field creating "copy C" of handles...but this copy has none of the updates from solicita_espacios. It then updates the handles structure with guidata(hObject,handles) and returns to the calling function which still has the "copy A" handles structure.
At no time, does pushbutton1_Callback ever get the updated handles structure.
So try changing your code as follows, so that your two functions return the updated handles structure. Change the two function signatures to
function [handles] = solicita_espacios(hObject, eventdata, handles)
function [handles] = solicita_mapas(hObject, eventdata, handles)
and in pushbutton1_Callback, change these function calls from
solicita_espacios(hObject, eventdata, handles);
solicita_mapas(hObject, eventdata,handles);
to
handles = solicita_espacios(hObject, eventdata, handles);
handles = solicita_mapas(hObject, eventdata,handles);
you don't know how grateful i am, i was desperate. thanks a lot.
Glad it worked out!
Geof can you help me? i found a little problem when i use the function solicita_mapas, the m variable should be a cell but every value of m should be a char.
in my function every value of m is cell.
if i use a fixed value like this works fine:
mm={
'E:\spm8\tpm\grey.nii'
'E:\spm8\tpm\white.nii'
'E:\spm8\tpm\csf.nii'};
Please see the attach to understand me.
function [handles] = solicita_mapas(hObject, eventdata, handles)
y=3*(str2double(get(handles.edit4,'String'))); %cantidad de mapas que se multiplica por 3 para formar los conjuntos
for i=1:y %%se hace ciclo for para seleccionar uno a uno los mapas de probabilidad .nii
[FileName,PathName] = uigetfile('*.nii',['Seleccione el mapa de probabilidad ',num2str(i)]);
FileName = cellstr(FileName); %pone el nombre en string
PathName = cellstr(PathName); %pone la ruta en string
m{i,1}=(strcat(PathName,FileName));
end
cuenta=0;
col=1;
f=1;
for z=1:numel(m); %%cuenta y separa de a tres cada grupo de mapas .nii por columnas
celdaMap{f,col}=m{z,1};
cuenta=cuenta+1;
if cuenta==3
col=col+1;
cuenta=0;
end
if f==3
f=0;
end
f=f+1;
end
handles.celdaMap=celdaMap;
guidata(hObject,handles);
Steven - don't use cellstr to convert your file name and path name to a cell array of strings. Just do the following instead
m = cell(y,1);
for k=1:y
[FileName,PathName] = uigetfile('*.m',...
['Seleccione el mapa de probabilidad ',num2str(k)]);
m{k,1}=fullfile(PathName,FileName);
end
Note the changes in the above - the m cell array is pre-sized with y rows and one column; the k is used instead of i since i and j are also used to represent the imaginary number, and fullfile is used to concatenate the path and file name (it will insert the appropriate forward or backward slash between the folder path and file name).
thank you, it works perfectly
hi, it´s me again, i need to validate if a variable exist to create a string and show it in edit but always came a 0 value, what i´m doing wrong?
if(exist('handles.strSpaceMG')==1);
if(exist('handles.strSpaceMB')==1);
if(exist('handles.strSpaceLC')==1);
StrEspacios=strcat(handles.strSpaceMG, handles.strSpaceMB, handles.strSpacLC);% create a string because exist the 3 variables, but always came a cero value thats the problem
end
StrEspacios=strcat(handles.strSpaceMG, handles.strSpaceMB);
end
StrEspacios=strcat(handles.strSpaceMG);
end
set(handles.edit8,'String',StrEspacios);
Steven - you should post this as a new question as it does not relate to the the original one.
That being said, look at how you are using exist
if(exist('handles.strSpaceMG')==1);
If you are checking to see if a field is a member of a structure, then you should use isfield as
if isfield(handles,'strSpaceMG')
Try the above and if you can't get it to work, then please post this as a separate question.
it works perfectly, again thank you.

Accedi per commentare.

Più risposte (0)

Categorie

Prodotti

Community Treasure Hunt

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

Start Hunting!

Translated by