what command or box do i use to get a dynamic input box on app design GUI

I am trying to find a command or input box where I can make dynamic inputs to plort on the graph. I want it to take in the value of the no of sensors in rthe GUI and the then open an input box asking for the coorinates of each sensor
for example :-
No of sensors= 3
an input box asking for 3 sets of X and Y coordinates to plot on the graph
No of sensors= 4
an input box asking for 4 sets of X and Y coordinates to plot on the graph

1 Comment

I have figured out how to edit the uitable but i am trying to figure out how can i save the input vales, i added another add button to save the program but it is not working out and how can i plot the x and y values from the table using a scatter graph ?
properties (Access = private)
sensor_table = gobjects(1,1); %initialize as graphics object
sensor_values
end
% Callbacks that handle component events
methods (Access = private)
% Button pushed function: RunButton
function RunButtonPushed(app, event)
platewidth=app.WidthEditField.Value;
plateheight=app.HeightEditField.Value;
GridWidth = app.GridWidthEditField.Value;
GridHeight = app.GridHeightEditField.Value;
Xcoordinate = app.XcoordinateEditField.Value;
Ycoordinate = app.YcoordinateEditField.Value;
Lengthofcell = app.LengthofcellEditField.Value;
Gridx = Xcoordinate : Lengthofcell : GridWidth+Xcoordinate;
Gridy = Ycoordinate : Lengthofcell : GridHeight+Ycoordinate;
if Gridx(end) >= platewidth
error('Grid x (%d) + grid width (%d) >= plate width (%d)', Xcoordinate, GridWidth, platewidth);
end
if Gridy(end) >= plateheight
error('Grid y (%d) + grid height (%d) >= plate height (%d)', Ycoordinate, GridHeight, plateheight);
end
Mx = length(Gridx);
My = length(Gridy);
[x, y] = meshgrid(Gridx, Gridy);
%create the list of text
labels = string(1:Mx*My).';
%insert the labels
hold(app.UIAxes, 'on')
scatter(app.UIAxes, x, y, "O", "MarkerFaceColor", 'r')
text(app.UIAxes, x(:), y(:), labels, 'HorizontalAlignment', 'left', 'verticalalignment', 'bottom')
%calculte the grid lines
grid1x = [Gridx;Gridx];
grid1y = [Gridy(1); Gridy(end)];
grid2x = [Gridx(1); Gridx(end)];
grid2y = [Gridy; Gridy].';
plot(app.UIAxes, grid1x, grid1y, "Color", 'b');
plot(app.UIAxes, grid2x, grid2y, "Color", 'b');
rectangle(app.UIAxes, 'Position', [0 0 platewidth plateheight],'LineWidth', 5);
box(app.UIAxes, 'on')
grid(app.UIAxes, 'on')
xlim(app.UIAxes,[0 platewidth])
ylim(app.UIAxes,[0 plateheight])
xticks(0:Xcoordinate:platewidth)
yticks(0:Ycoordinate:plateheight)
hold(app.UIAxes, 'off')
N = app.NoofSensorsEditField.Value;
sensor_number = (1:N).';
X_coordinate = zeros(N,1);
Y_coordinate = zeros(N,1);
T = table(sensor_number, X_coordinate, Y_coordinate);
app.sensor_table = uitable(app.UIFigure, 'Data', T);
app.sensor_table.ColumnEditable = true;
end
% Button pushed function: AddButton
function AddButtonPushed(app, event)
app.sensor_values=uitable(app.UIFigure, 'Data', T);

Sign in to comment.

 Accepted Answer

You are using App Designer, so you are probably using uifigure() as your base.
So you can have your code call uieditfield() to dynamically place an edit box onto the container. https://www.mathworks.com/help/matlab/ref/uieditfield.html
You can configure its ValueChangedFcn https://www.mathworks.com/help/matlab/ref/matlab.ui.control.numericeditfield-properties.html#buh_e24-76_sep_shared-ValueChangedFcn to invoke a callback when the user enters data into it. Or not, if you have some other way for the user to invoke action (which is probably the case since you want the user to enter in all the values before doing anything.)
If you do configure a callback, you would provide the handle to a function that you had already written. You would not try to write callback code dynamically! Instead, have all of the fields use the same callback code, with the callback distinguishing between the fields by their Tag or by some UserData you attached to the field.
If you do not have a maximum number of sensors that the user can enter, then you need to design in some kind of scroll box for the inputs. But if you are headed towards that, then uitable() is often an easier approach.
If you have a small fixed maximum number of sensors, then often the easiest approach is to design all of them with positions and callbacks and whatever ahead of time, but set them all to be invisible at the start, and then turn on only as many as need. This does not involve creating any objects dynamically, just making existing objects visible or invisible.

18 Comments

i think there arent any fixed number of sensors, so i dont think hard coding it would be wise, but if i set 50 as max number of sensor i can call them as i need and set the rest as (0,0)?
Yes, create a vector of the handles and then you can set() properties for a subset of the handles.
However for anywhere even close to 50 you are going to run out of screen, and so need a scrollable area. Instead of doing that kind of work yourself consider using a uitable. Which will also give you a lot of convenience when it comes to allowing the user to save and load configurations, which is a facility that you will surely need instead of making the user type in 50 sets of numbers.
Yes thank you, i will need to find a way to code it 😢
Having a single uitable() is the easiest way. Set the Data property to have as many rows as the number of sensors, and make the fields editable. If you need a different name for each sensor, write the name in as one of the pieces of data.
If you are using uifigure(), such as is the case for App Designer, then you can set the Data property to a table() object.
i am trying it but i am lost on how to write the code. i made a new app so that it is easier to code without confusion but i am unable to code logically as i dont have much experince in app design
properties (Access = private)
set(v) % Description
end
% Callbacks that handle component events
methods (Access = private)
% Button pushed function: Button
function ButtonPushed(app, event)
x="N of Sensors";
v=[1:50];
uitable=(uifigure,x,v);
properties (Access = private)
sensor_table = gobjects(1,1); %initialize as graphics object
end
methods (Access = private)
function ButtonPushed(app, event)
N = app.No_of_sensors.Value;
sensor_number = (1:N).';
x_coordinate = zeros(N,1);
y_coordinate = zeros(N,1);
T = table(sensor_number, x_coordinate, y_coordinate);
sensor_table = uitable(app.UIFigure, 'Data', T);
end
end
except that in your real code, you would also need to set Position information for the uitable(), and set the second and third columns to be editable. And possibly set the sensor_table VariableNames property to {'Sensor Number', 'X Coordinate', 'Y Coordinate'} or something like that more decorative.
how do i edit the table to add the values of x and y
properties (Access = private)
sensor_table = gobjects(1,1); %initialize as graphics object
end
% Callbacks that handle component events
methods (Access = private)
% Button pushed function: Button
function ButtonPushed(app, event)
N = app.NoofSensorsEditField.Value;
sensor_number = (1:N).';
x_coordinate = zeros(N,1);
y_coordinate = zeros(N,1);
T = table(sensor_number, x_coordinate, y_coordinate);
app.sensor_table = uitable(app.UIFigure, 'Data', T);
edt=uieditfield(app.sensor_table,"CreateFcn",x_coordinate);
it is a silly question but can i know what this piece of code does in the program, if i am not wrong it just displays the table
sensor_table = uitable(app.UIFigure, 'Data', T);
Yes, it displays a table. However, no Position was specified so it might not be a convenient size or position.
SO THIS CODE HAS THE NEW EDITED DATA ? IF I WANNA SAVE THE NEW VALUES, IT SHOULD BE SOMETHING FROM THIS PIECE OF CODE?
app.T = table(app.sensor_number, app.x_coordinate, app.y_coordinate,'VariableNames',{'sensor number' 'x coordinate' 'y coordinate'});
When you use uitable() with those parameters, unless you set properties of the table afterwards, it will not be editable, so there will not be any "new edited data" . At least one column would have had to have been set ColumnEditable in order for the user to be able to edit the table.
When you let a user edit a uitable, only the copy stored in the properties of the uitable is affected: letting the user edit the uitable will not affect a previously stored app.T
If what you are using is how to get the data in app.T displayed in a table, then the answer is
sensor_table = uitable(app.UIFigure, 'Data', app.T);
however, setting Position is recommended as the defaults are not necessarily useful.
(Note to other readers: the above only works for uitable() created within a uifigure() such as App Designer uses. uitable() within traditional figures do not have the ability to process table() objects.)
so how can i extract data that i have added to the table ?, it would be from this line of code, if i am not wrong.
T = table(sensor_number, X_coordinate, Y_coordinate);
i have tried to extract the colomns by means of save or set it as a diffent variable but was unsucessful
Are you trying to extract the data from the variable app.T that you assigned? Or are you trying to extract the data from the uitable that you created?
If you are trying to extract it from app.T then you can
T = app.T;
save('YourFileName.mat', 'T');
or you can
sensor_number = app.T.sensor_number;
X_coordinate = app.T.X_coordinate;
Y_coordinate = app.T.Y_coordinate;
save('YourFileName.mat', 'sensor_number', 'X_coordinate', 'Y_coordinate');
I tried both the techniques that you suggested in the add call back but i got the same error, was i mean to add those in the RUN call back it didnt make any sense to me.
% Callbacks that handle component events
methods (Access = private)
% Button pushed function: RunButton
function RunButtonPushed(app, event)
N = app.NoofSensorsEditField.Value;
sensor_number = (1:N).';
x_coordinate = zeros(N,1);
y_coordinate = zeros(N,1);
app.T = table(sensor_number,x_coordinate,y_coordinate,'VariableNames',{'sensor number' 'x coordinate' 'y coordinate'});
app.sensor_table = uitable(app.UIFigure, 'Data', app.T, "ColumnEditable",[false true true] );
end
% Button pushed function: ADDButton
function ADDButtonPushed(app, event)
sensor_number = app.T.sensor_number;
X_coordinate = app.T.X_coordinate;
Y_coordinate = app.T.Y_coordinate;
save('YourFileName.mat', 'sensor_number', 'X_coordinate', 'Y_coordinate');
Hence i converted even X_coordinates and Y_coordinates into properties. via this it is atleast plotting but not able to take new values
roperties (Access = private)
sensor_table = gobjects(1,1); %initialize as graphics object
T % Table to be shared between callbacks
sensor_number
x_coordinate
y_coordinate
end
% Callbacks that handle component events
methods (Access = private)
% Button pushed function: RunButton
function RunButtonPushed(app, event)
N = app.NoofSensorsEditField.Value;
app.sensor_number = (1:N).';
app.x_coordinate = zeros(N,1);
app.y_coordinate = zeros(N,1);
app.T = table(app.sensor_number, app.x_coordinate, app.y_coordinate,'VariableNames',{'sensor number' 'x coordinate' 'y coordinate'});
app.sensor_table = uitable(app.UIFigure, 'Data', app.T, "ColumnEditable",[false true true] );
end
% Button pushed function: ADDButton
function ADDButtonPushed(app, event)
save('app13.mlapp', 'app.sensor_number', 'app.X_coordinate', 'app.Y_coordinate')
scatter(app.UIAxes,app.x_coordinate, app.y_coordinate,"O", "MarkerFaceColor", 'g');
I tried addding app.T or app.sensor_number, app.X_coordinate, app.Y_coordinate i get the same error Error using save 'app.sensor_number' is not a valid variable name.
Can i use the save function as .Xls file instead of .mat file ? will it create a new excel sheet and would the new data be stored in that ? does it work ? thank you
It will never be possible to save part of the variable app using save(). You must extract into local variables... the way I showed.
properties (Access = private)
sensor_table = gobjects(1,1); %initialize as graphics object
end
% Callbacks that handle component events
methods (Access = private)
% Button pushed function: RunButton
function RunButtonPushed(app, event)
%these are local variables. Leave them as local variables.
N = app.NoofSensorsEditField.Value;
sensor_number = (1:N).';
x_coordinate = zeros(N,1);
y_coordinate = zeros(N,1);
T = table(sensor_number, x_coordinate, y_coordinate,'VariableNames',{'sensor number' 'x coordinate' 'y coordinate'});
%okay, THIS can be an app property
app.sensor_table = uitable(app.UIFigure, 'Data', T, "ColumnEditable",[false true true] );
end
% Button pushed function: ADDButton
function ADDButtonPushed(app, event)
%these are local variables. Leave them as local variables.
sensor_number = app.sensor_table.Data.('sensor number');
x_coordinate = app.sensor_table.Data.('x coordinate');
y_coordinate = app.sensor_table.Data.('y coordiante');
save('app13.mat', 'sensor_number', 'X_coordinate', 'Y_coordinate');
scatter(app.UIAxes, x_coordinate, y_coordinate, "O", "MarkerFaceColor", 'g');
end
end
Can i use the save function as .Xls file instead of .mat file ?
No. However, you could
sheetname = something appropriate
writetable(app.sensor_table.Data, 'app13.xls', 'sheet', sheetname);

Sign in to comment.

More Answers (1)

2 Comments

Yea thanks im trying to figure it out for my command
Yeah Uitable isn't the thing we're looking for That code didn't really output much after I rechecked errors But I researched on uitable that isn't what i need inputdlg is something that i was trying But I don't know what's the next step

Sign in to comment.

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Products

Release

R2021a

Community Treasure Hunt

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

Start Hunting!