Why does my method doesn't recognise the variable U that I defined as global?

I wrote a method in the designer app, so that I can call the functions that I need without writting them every time for each button. But I get a little error while executing the third function ( in the for =1:numel(U)) line:
methods (Access = public)
function implement = loadingdata(app) % first function for loading data
load data.mat Table1
load data.mat Table2
.. end
function input = timeandfrequency(app) % 2nd function for the input windows
answer = questdlg('Is there a time stamp?',...
'Please give the time stamp',...
'yes','no','no');
if (answer == "yes")
prompt ={' type the start time in [HH:MM:SS] ','Type the endtime in [HH::MM:SS]'};
dlgtitle = 'Time in HH:MM:SS';
dims =[1 40];
definput = {'13:20:00','13:50:00'};
time_answer = inputdlg(prompt,dlgtitle,dims,definput);
st = time_answer{1,:};
et = time_answer{2,:};
end
answer = questdlg(' Which Frequency would you like to plot ?', ...
'', ...
'Frequency 1','Frequency 2','Frequency 3','Frequency 3');
end
function plotting = diagrams(app) % third function for plotting the data
for k = 1:numel(U)
Var = Variableunits.Variable;
Num = size(Var,1);
X = T.Variable==U(k);
Uhrzeit = round(seconds(T.Time(X)/1000)); %Umwandlung der Uhrzeit zum Format HH:MM:SS
Uhrzeit.Format='hh:mm:ss';
Uhrzeit = sort( Uhrzeit,'ascend');
Wert = T.Value(X);
if (answer == "yes") % Wenn ein Zeitstempel vorhanden ist
ind = find(Uhrzeit >= st & Uhrzeit <= et);%Die Uhrzeit zwischen Anfangsuhrzeit und Endzeit einschränken
Uhrzeit = Uhrzeit(ind);
Wert = Wert(ind);
end
switch answer
case 'Frequency 1'
....
case 'Frequency 2'
....
case 'Frequency 3'
....
end %switch
end %for
end %function
end %method
After executing the first button as an example, it calls the 3 function and then I get the error: Unrecognised function or variable U in the method, despite defining it as a global variable below:
% Button pushed function: Variable1Button
function H2_TEMPERATURE_Pt01CelsiusButtonPushed(app, event)
loadingdata(app) % first function
timeandfrequency(app)% second function
global Us
global U;
Us = ["Variable1"];
U = categorical(Us);
%for loop
diagrams(app) % third function
Why does the function cant recognise the variable U? How can the method recognises it from the button function?

 Réponse acceptée

Adam Danz
Adam Danz le 4 Déc 2020
Modifié(e) : Adam Danz le 4 Déc 2020
Don't use Global variables, especially in AppDesigner!
Instead, declare variables that are shared between app functions as private or public properties.
Private properties are for variables shared interally within the app. Public properties are for variables shared externally to the mlapp file.
See Matlab's documentation on app properties
Step 1: Declare the variable as a private|public property.
Add the property using the green "+" in the image below (in code view, within AppDesigner)
A private | public declaration will be automatically added to the code. Change the name of "Property" to the variable name.
It's also a good idea to give the variable a default value. I named the variable "myDescriptiveVariableName" and set it as NaN.
Step 2: Use the variable anywhere in the app
To use this variable, simply use app.myDescriptiveVariableName. Any function can update the value stored in that property.
For public variables accessed outside of the app, you just need the app handle and then you can access the variable in the same way as shown above.
Here are some reviews about how to get the app handle outside of the app

6 commentaires

Thank you Adam for the detailed answer. I added properties for all the variables that I have. There is just one problem is that the code does not plot properly. Along with the code that I added above (see the comment below:
nexttile
yyaxis left
plot(app.ftime,app.freq)
hold on
yyaxis right
plot(app.Uhrzeit,app.Wert); % I get an error on this line:
% Data inputs must match the axis configuration. A numeric axis must have numeric data inputs or data inputs which can be converted to double.
for i = 1:Num
if app.Var(i) == app.U(k)
app.thisunit = app.Unit(i);
if ismissing(app.thisunit)
thisunitname = '';
else
thisunitname = string(app.thisunit);
end
legend('Variable','Frequency');
title(string(app.Var(i)) + " " + thisunitname + " 10^" + string(app.NKS(i)), 'Interpreter', 'none');
end
end
hold off
end
end
end
What does the reason might be for the error?
It suggests that this line
plot(app.ftime,app.freq)
produces a plot from numeric data (as opposed to logical, categorical, etc) but this line
plot(app.Uhrzeit,app.Wert);
contains non-numeric data that needs to be converted to numeric.
These lines below will tell you the class of the data
class(app.Uhrzeit)
class(app.Wert)
Hi Adam. I know I have been asking so many questions lately, and I am really thankful for your immense help. I just feel like I am making it really worse that the code does not even plot anymore:
case 'Frequency 1'
app.freq1 = double(split(string(app.freq1(1:end-1)) , ","));
app.freq = double (app.freq1(:,1));
app.ftime=linspace(app.Uhrzeit(1),app.Uhrzeit(end-1),height(table(app.freq1table)));
% app.ftime=app.ftime';
app.ftime = app.ftime(1:end-1);
app.ftime = round(seconds(app.ftime/1000));
app.ftime.Format='hh:mm:ss';
Thanks to those two lines you ve written that tell which class has each data, I found out that even though I added the round function for the app.ftime variable and converted it to the 'hh:mm:ss" format. the app.ftime variable has a struct class data and I am not quite sure what is the cause for this. Which I guess gives the error to the plot(app.ftime,app.freq) line:
Error using plot
Invalid data argument.
How can I force a variable (in this case app.ftime ) to be converted to a duration type so that I can be able to plot it (on the x-axis)?
Thanks you so much Adam. I hope this is my last question for now XD, in case I should open a new question about this or it is not okay putting another question in here, let me know
I don't have enough information to understand what's wrong with the snippet of code you shared in your comment above. There are some curious parts in there such as the conversion of app.freq1 (whatever that is) to string and then to double. Plus I don't see the plotting code and how these variables contirbute to the plot.
> the app.ftime variable has a struct class data and I am not quite sure what is the cause for this
Neither am I! Perhpas one of the matlab functions you're using is shadowed by a custom function or scripts with the same name. Maybe app.ftime becomes a structure later in the code.
% This line assigns a vector of numbers to app.ftime.
% It's unclear why you're creating a table in the 3rd argument
app.ftime=linspace(app.Uhrzeit(1),app.Uhrzeit(end-1),height(table(app.freq1table)));
% This line converts the row vector to a column vector
% It could be combined with the first line above.
% app.ftime=app.ftime';
% This removes the last value
% Another way of doing that is app.ftime(end)=[];
app.ftime = app.ftime(1:end-1);
% This converts the numeric column vector to a duration in
% seconds, rounded.
app.ftime = round(seconds(app.ftime/1000));
% This changes the displayed format
app.ftime.Format='hh:mm:ss';
What you need to do is learn how to use debug mode so you can explore the variables in each line.
This is straightforward and I've tried to implement it by loading a time series image in startupFcn and then send the image stack to properties for availability to other functions in the app. However, the image stack is emtpy coming from properties. Like this:
% Code that executes after component creation
function startupFcn(app)
% preload image frame number
app.FramemEditField.Value = 1;
app.FrameEditField_2.Value = 1;
app.FrameEditField.Value = 1;
% configure image axes
app.ImageAxes.Visible = 'on';
app.ImageAxes_2.Visible = 'on';
app.ImageAxes_3.Visible = 'on';
app.ImageAxes_5.Visible = 'on';
app.ImageAxes_7.Visible = 'on';
filterspec = {'*.det', '.det files'};
[f, p] = uigetfile(filterspec);
if (ischar(p))
fname = [p f];
[detfile_hg, detfile_lg, frametype, counter, trigger, frameindex] = ReadDet(fname, 4680, 200, 3, 1);
end
and then I add the outputs to properties, like this:
properties (Access = public)
% Description: store the .det file
detfile_hg;
detfile_lg;
frametype;
end
but when I call them from another function, something like a LoadImageButton_aoiPushed function using this call:
detfile = permute(app.detfile_hg, [2 1 3]);
the variable is empty. Where have I gone wrong?
Thanks in advance
You're not storing the value to the app properties. You're storing the to variables that have the same name as the app properties but those variables are cleared at the end of the function.
[detfile_hg, detfile_lg, frametype, counter, trigger, frameindex] = ReadDet
this should be
[app.detfile_hg, app.detfile_lg, app.frametype, counter, trigger, frameindex] = ReadDet(...)
Also, those properties are only defined when p is a char so think about setting default values when you declare the properties
properties (Access = public)
% Description: store the .det file
detfile_hg = 0; % for example...
...
end

Connectez-vous pour commenter.

Plus de réponses (1)

Théophane Dimier
Théophane Dimier le 4 Déc 2020
Modifié(e) : Théophane Dimier le 4 Déc 2020
you need to redeclare "global U" at the beginning your 3rd function, to create a variable "U" in that functions's workspace and to "synchronize" it with the other "U" variable

1 commentaire

but anyway, passing the variable U as an argument of the 3rd function would certainly be safer. As a general practice, global variable should be avoided as much as possible.

Connectez-vous pour commenter.

Catégories

Community Treasure Hunt

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

Start Hunting!

Translated by