Uploading a value with a Matrix into MATLAB GUI

Hello Guys. I hope you are doing well. I have a question related to the uploading the value with a matrix. My code for the upload_ callback is working for all values except for the edit text box with a matrix and a value. How can I change the code below so that I can upload the value with the matrix as well? Any help will be greatly appreciated. I get the following errors when I use the pushbutton upload code shown below. These errors only come when I try to upload the value with the matrix edit box and not for the other edit text boxes.
Error using sprintf
Function is not defined for 'cell' inputs.
Error in GUI_ParametersFinal>pushbutton_Upload_Callback (line 149)
evalstr = sprintf('set(handles.%s,''%s'',''%s'')',uictagnames{i}, uicparams{j},tempval);
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in GUI_ParametersFinal (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in @(hObject,eventdata)GUI_ParametersFinal('pushbutton_Upload_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback
The code is:
function pushbutton_Upload_Callback(hObject, eventdata, handles)
startingFolder = pwd
defaultFileName = fullfile(startingFolder, '*.mat');
[baseFileName, folder] = uigetfile(defaultFileName, 'Select a mat file');
if baseFileName == 0
return;
end
fullFileName = fullfile(folder, baseFileName)
temp = load(fullFileName);
data=temp.data;
uictagnames = fieldnames(data);
for i =1:numel(uictagnames)
uicparams = fieldnames(data.(uictagnames{i}));
for j = 1:numel(uicparams)
tempval = data.(uictagnames{i}).(uicparams{j});
if ~isnumeric(tempval)
evalstr = sprintf('set(handles.%s,''%s'',''%s'')',uictagnames{i}, uicparams{j},tempval);
else
evalstr = sprintf('set(handles.%s,''%s'',%d)',uictagnames{i}, uicparams{j}, tempval);
end
evalc(evalstr);
end
end
For edit callbacks, I am using this code:
str=get(hObject,'String');
tagname=get(hObject,'tag');
handles.mystructdata.(tagname).string = str;
guidata(hObject,handles)
The value in the edit text box is being generated from another GUI in the button down function. The value is getting saved, but once I click on the upload button, all the values get uploaded except for the value shown below because it is a value with matrix.
For all other structs, I have 1 fields. Only for this struct, I have 2 fields. Any help will be greatly admired as I am working on a big project. I had taken the help for uploading the values of the edit text boxes from this link. Therefore, you can see the link as well. I just need to upload the value with the matrix as shown above. Everthing else is done.

1 comentario

Stephen23
Stephen23 el 21 de Oct. de 2019
Editada: Stephen23 el 21 de Oct. de 2019
The link you gave uses really very badly writen code: in general, I would not recommend copying code from people asking questions: the reason they are asking questions is because they don't know what they are doing. And anyone using evalc to set the field of a handles structure really doesn't know what they are doing.

Iniciar sesión para comentar.

 Respuesta aceptada

Stephen23
Stephen23 el 21 de Oct. de 2019
Editada: Stephen23 el 21 de Oct. de 2019
Clearly tempval is a cell array, which as the error message makes quite clear, sprintf cannot handle. But regardless, that is a very inadvisable approach to setting an object property.
You would easily avoid this error if you had followed my earlier advice to NOT use that awful evalc code. I have given you the link to the documentation several times, and also given you examples of how to use dynamic fieldnames:
set(handles.(uictagnames{i}), uicparams{j}, tempval)
Of course this assumes that the object accepts a cell array for that property: if that is not the case, then you will need to fix your code so that you do not try to set the property with a cell array.

16 comentarios

Debug your code! Set
dbstop if error
and then show the output of these commands:
fieldnames(handles)
uictagnames{i}
uicparams{j}
Stephen23
Stephen23 el 22 de Oct. de 2019
Editada: Stephen23 el 22 de Oct. de 2019
"The problem is all my fields are being saved as string except for the last one"
I presume that by "last one" you are referring to the field named MaturityL... (the complete name is obscured in your screenshot). If so, then judging by the name is its data numeric? Is
if ~isnumeric(tempval)
...
end
really required? What does it do in your code?
Please place these commands after the loops, and show their outputs:
disp(i)
disp(j)
uictagnames{i}
uicparams{j}
size(uicparams)
get(handles.MaturityLevel,'Matrix')
get(handles.MaturityLevel,'Value')
Stephen23
Stephen23 el 24 de Oct. de 2019
@MHS: if you upload the code and required data here in a comment then I will take a look at it,
Stephen23
Stephen23 el 24 de Oct. de 2019
Editada: Stephen23 el 24 de Oct. de 2019
@MHS: exactly as the error states, your handles structure does not contain a MaturityLevel field. It does however contain an edit_MaturityLevel field:
So you will need to do either of these:
  1. change the fieldname of the data saved in the .mat file to actually match the fieldname in the handles structure, or
  2. add some data-munging code that somehow converts/matches those fieldnames.
"If you can edit the code to make the Maturity Level value upload on the GUI, this is all what I need because it is not having a string but a matrix and a value."
I would resolve it by simplifying the data you actually save in the .mat file. In particular, note how your nested structures do not have any added value, because (almost) all of the nested structures are scalar and have exactly one field (named string). Change the saving code to simply save the string data directly in the field, rather than in that nested structure:
S.edit_one = 'hello';
S.edit_two = 'world';
...
S.edit_maturityLevel = 'X50';
save(...,'-struct','S')
Then all you need in your "importing" code is this:
data = load(...);
fnm = fieldnames(data);
for k = 1:numel(fnm)
set(handles.(fnm{k}), 'String', data.(fnm{k}));
end
I would avoid messing around trying to match unmatching fieldnames, better to fix the problem at its source. Simpler data -.> simpler code -> more efficient, fewer bugs, easier to debug.
However if you really just want to get this going without redesigning your data, then try this:
data = temp.data;
fnms = fieldnames(data);
for k = 1:numel(fnms)
if strcmpi(fnms{k},'MaturityLevel')
set(handles.edit_MaturityLevel, 'String',data.MaturityLevel.Value);
else
set(handles.(fnms{k}), 'String',data.(fnms{k}).string);
end
end
That worked for me:
Capture.PNG
Stephen23
Stephen23 el 24 de Oct. de 2019
Editada: Stephen23 el 24 de Oct. de 2019
"...but there is one problem. The value of Maturity Level is not fixed,..."
The code at the end of my last comment sets the edit box text to whatever MaturityLevel.Value that is saved in the mat file, which is what I though you were trying to do. It is certainly not "fixed".
"How can I save it as a a variable string so that it can save any value?"
I don't understand that question, which means both of us are confused!
As I wrote in my earlier comment, simplifying your saved data would actually make your task a lot easier. I also gave you a workaround for your differing fieldnames and tested it (see screenshot), that uses your .mat file's MaturityLevel.Value data.
"I need to save the matrix, which I did."
Sure, if you need it, then save it. Your code complexity (and possibly your confusion) seems to come from your attempt to write "universal" code that works for all of your data, but what you show and describe is that MaturityLevel is a special case with extra data (it has more data, different fieldnames)... .if so, don't be scared of treating it as a special case AND also simplifying the remaining data and code (as I described in my earlier comment).
Simplify your data, simplify your code, simplify your thinking.
Note that .mat files can cotnain multiple variables, so one trivial solution would be to save one structure of the edit_... boxes (no nested structures!), and one structure for MaturityLevel (with matrix and value fields).
Stephen23
Stephen23 el 24 de Oct. de 2019
Editada: Stephen23 el 24 de Oct. de 2019
"Its really suprising that its working for the testmatfile, but not for other files."
It is not very surprising at all:
  • testmatfile.mat contains multiple scalar structures nested inside a scalar structure named data.
  • matlab_check.mat contains multiple scalar structures as separate variables.
Different mat file variables arranged in two totally different ways produce different code responses. What is surprising about that?
It appears that you saved matlab_check.mat using save's -struct syntax, but then tried to access data = temp.data. In that case your code will throw an error, because the entire point of the -struct syntax is that the .mat file does not contain the data variable.
MHS
MHS el 24 de Oct. de 2019
Editada: MHS el 24 de Oct. de 2019
Thank you so much. Means a lot. You have solved my one week long problem. I can go further now. May God bless you :) I will try to do it with other way as well when I will finish it to simplify my code.
Stephen23
Stephen23 el 5 de Nov. de 2019
Editada: Stephen23 el 5 de Nov. de 2019
You are calling setappdata with the GUI handle, but you are calling getappdata with the graphics root 0, so it is not clear when isappdata would ever be true: you appear to be checking for data that you never save (in that specific location).
MHS
MHS el 5 de Nov. de 2019
Editada: MHS el 5 de Nov. de 2019
Hello Stephen. Thanks for your answer, but I just tried to change it to both options with handles as well as graphics root 0 before asking you. Now, I have tried to save and call everything with the graphics root 0, but it is not working for me. You can see in the files. You can have a look at my both files and let me know what was my problem and how could i have figured this? Only when I close the parameters GUI and run it again, the Maturity Level GUI should show the previous Maturity Level options selection for radiobuttons checkboxes samples everything on clicking upon the button down function of the Maturity Level so that user can remember what he had selected last time if he clicks on uploading the previous maturity level. It will be so nice of you. Thank you so much. You can just check by running both GUIs together.
Stephen23
Stephen23 el 5 de Nov. de 2019
Editada: Stephen23 el 5 de Nov. de 2019
@MHS: your code logic does not make much sense to me.
In GUI_MaturityLevel.m you apparently try to use the MaturityLevelSaved property in the graphics root, but within the two M-files that you provided the only instance of setappdata with that property name is in GUI_ParametersFinal.m like this:
if isappdata(0, 'MaturityLevelSaved')
setappdata(0,'MaturityLevelSaved', MaturityLevelSaved) %Store the data into figure workspace
MaturityLevelSaved =getappdata(h, 'MaturityLevelSaved'); % Retrieve variables from figure's workspace.
rmappdata(0, 'MaturityLevelSaved'); %Remove from figure workspace
end;
Note how the code inside the if will only be evaluated if MaturityLevelSaved is already a property of the graphics root: if it is not a property of the graphics root (which it is unlikely to be when you start MATLAB), then your code will never create that property.
And even if somehow magically that property did exist, you immediately delete it using rmappdata(0, 'MaturityLevelSaved').
So it is very unlikely that you ever create that property, and even if you did, you delete it straight away... what do you expect to happen?
MHS
MHS el 5 de Nov. de 2019
Editada: MHS el 5 de Nov. de 2019
Thanks. I am just trying to make it simple, but its not working. In GUI_ParametersFinal.m, I am just saving it.
if isappdata(0, 'MaturityLevelSaved')
setappdata(0,'MaturityLevelSaved', MaturityLevelSaved) %Store the data into figure workspace
end;
In GUI_MaturityLevel.m, I am retrieving the variables from figure workspace.
function GUI_MaturityLevel_OpeningFcn(hObject, eventdata, handles, varargin)
if isappdata(0, 'MaturityLevelSaved')
handles.MaturityLevel =getappdata(0, 'MaturityLevelSaved'); % Retrieve variables from figure's workspace.
Characteristics ={AKS', 'Demagnetization', 'Firmness', 'Thermal', 'CoggingTorque', 'Acoustics', 'MagnetLosses'};
for i=1:length(Characteristics)
for j=2:3
if MaturityLevel.Matrix{i+2,j-1}=='x'
handles.(['radiobutton_', Characteristics{i}, int2str(j)]).Value=1;
end
end
end
end
handles.output = hObject;
guidata(hObject, handles);
Why is it not working now? Please help. Thanks once again. I am just saving in the main GUI and retrieving it with the other GUI, which was my main idea. It does not exist for MaturityLevelSaved property. What is the reason for this? But is it possible that it will work with the property of the Graphics root?
"Why is it not working now?"
For exactly the same reason that I wrote in my last comment. When will this be true?:
if isappdata(0, 'MaturityLevelSaved')
Stephen23
Stephen23 el 5 de Nov. de 2019
Editada: Stephen23 el 5 de Nov. de 2019
@MSH: what do you expect these lines to do?:
setappdata(0,'MaturityLevelSaved', MaturityLevelSaved) %Store the data into figure workspace
MaturityLevelSaved =getappdata(h, 'MaturityLevelSaved'); % Retrieve variables from figure's workspace.
Note how you first define the variable MaturityLevelSaved after you try to access it. At the point you try to access it, MaturityLevelSaved does not exist (and so trying to acess it will throw an error).
You really need to learn how to debug your own code. Debugging via random strangers on the internet is not very efficient for such complex code. You could have found all of these logical and syntactical mistakes yourself in just a few minutes.
Stephen23
Stephen23 el 5 de Nov. de 2019
Editada: Stephen23 el 5 de Nov. de 2019
@MHS: look at what your code is doing. For example, when I search for the text MaturityLevelSaved in your two M-files, nowhere is this property actually defined for the GUI_MaturityLevel GUI itself, so what do you expect this to return?:
h=GUI_MaturityLevel(..);
..
.. = getappdata(h, 'MaturityLevelSaved'); % Retrieve variables from figure's workspace.
Without saving the property MaturityLevelSaved in the GUI, what arrays or values do you expect to get when you getappdata that GUI property?
Although your comment states "Retrieve variables from figure's workspace", I can't find anywhere in your code where you store that property in the figure. Note that I am not the GUI designer, I cannot decide which callback should be storing that property value, or under which circumstances.
You need to know that, and check that.
Probably you should do these two steps:
  1. review all of the properties that you require, check that they are actually defined in the appropriate locations (so far I have found that the two main properties were never even created, something you could easily have found out yourself).
  2. use breakpoints to stop the code on particular lines and/or on error. Check the values. Add new breakpoints accordingly, work backwards until you know where those values come from and why.
Learning to debug is an importnat part of learning how to write code. You need to learn how to do this yourself.

Iniciar sesión para comentar.

Más respuestas (0)

Preguntada:

MHS
el 21 de Oct. de 2019

Comentada:

el 13 de Nov. de 2019

Community Treasure Hunt

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

Start Hunting!

Translated by