how to get a value from a drop down menu in matlab

Im trying to programmatically build a UI, im doing it this way because I have some complicated surfaces that I want to calculate and I want to do it for thousands of files. The matlab code do this is done, but I have a few pop up messages and input boxes that work, its clunky to say the least so im trying to clean it up with uifigure. Right now in my regular matlab code that I have been building, an input box pops up that asks if you want to and how to save data (i.e. either as a csv or txt file), if you want to move data and what type of surface you want to build. If a "calculated surface" if chosen, another input box pops up and asks if you want a surface with lowess smoothing or cubic interpolation, this only pops up if you choose the right option.
In uifigure im trying to duplicate this, I have a drop down that asks what kind of surface you want to create, if a "calculated surface" is chosen, I want another drop down menu to show up asking what type of calculated surface you want to make. This is where im having trouble and I need to figure it out before I can add in my other calculations. When I select a drop down option, dd1.Value is not changing, it stays at 0, in the switch function at the bottom im trying to say if dd1.Value = 2 then dd3.Visible = 'on'. When I run it, everything works fine however dd1.Value isnt changing depnding on user selection and im not sure where im going wrong or what I need to add. Any advice is appreciated. Thanks!
close all
fig = uifigure("Name", 'Single Beam Processing', 'Position', [30,75,1450,750]);
panel1 = uipanel(fig, "Position", [50,350,200,350]);
panel1.Title = "Program Setup";
panel1.TitlePosition = 'centertop';
panel1.FontSize = 14;
txtbox1 = uieditfield(panel1,"Text", "Position", [10,290,180,30], "Value", "Operator Name");
dd1 = uidropdown(panel1, 'Position', [10,250,180,30]);
dd1.Items = ["Choose Surface Type", "Depth", "Calculated Surface", "Fitted Plane", "Corrected Points", "None"];
dd1.ItemsData = [0 1 2 3 4 5];
dd1.Visible = 'on';
dd1value = dd1.Value;
dd2 = uidropdown(panel1, 'Position', [10,210,180,30]);
dd2.Items = ["Choose Save Options", "Save as CSV", "Save as txt"];
dd2.ItemsData = [0 1 2];
dd1.Visible = 'on';
dd2value = dd2.Value;
dd3 = uidropdown(panel1, 'Position', [10,170,180,30]);
dd3.Items = ["Choose Smoothing Type", "Lowess", "Cubic Interpolation"];
dd3.ItemsData = [0 1 2];
dd3.Visible = 'off';
switch dd1value
case 2
dd3.Visible = 'on';
otherwise
dd3.Visible = 'off';
end

 Accepted Answer

Voss
Voss on 20 Mar 2024
Edited: Voss on 21 Mar 2024
That line executes immediately after dd1 is created/set-up, so dd1value is whatever Value dd1 has initially. That is to say, that line executes before you have a chance to make a selection in dd1.
To be able to make selections and then use them for subsequent calculations, you need to make the program wait for the user. In a programmatic dialog like this, that typically means calling uiwait.
As for the question of having the selection made in dd1 change the visibility of dd3, you need to give dd1 a ValueChangedFcn, which executes when dd1's Value changes. In that function, you'll set the visibility of dd2 appropriately.
See the below code for those modifications. I also added a button the user clicks to signal that the selections are done, so the program should prepare the outputs and close the figure.
function [name,dd1_option,dd2_option,dd3_option] = Surface_Options()
fig = uifigure("Name", 'Single Beam Processing', 'Position', [30,75,1450,750]);
panel1 = uipanel(fig, "Position", [50,350,200,350]);
panel1.Title = "Program Setup";
panel1.TitlePosition = 'centertop';
panel1.FontSize = 14;
txtbox1 = uieditfield(panel1,"Text", "Position", [10,290,180,30], "Value", "Operator Name");
dd1 = uidropdown(panel1, 'Position', [10,250,180,30], 'ValueChangedFcn', @vcf_dd1);
dd1.Items = ["Choose Surface Type", "Depth", "Calculated Surface", "Fitted Plane", "Corrected Points", "None"];
dd1.ItemsData = [0 1 2 3 4 5];
dd1.Visible = 'on';
dd2 = uidropdown(panel1, 'Position', [10,210,180,30]);
dd2.Items = ["Choose Save Options", "Save as CSV", "Save as txt"];
dd2.ItemsData = [0 1 2];
dd1.Visible = 'on';
dd3 = uidropdown(panel1, 'Position', [10,170,180,30]);
dd3.Items = ["Choose Smoothing Type", "Lowess", "Cubic Interpolation"];
dd3.ItemsData = [0 1 2];
dd3.Visible = 'off';
uibutton(fig,'Position',[20 10 65 22],'Text','OK','ButtonPushedFcn',@bpf_btn);
% initialize outputs
name = txtbox1.Value;
dd1_option = dd1.Value;
dd2_option = dd2.Value;
dd3_option = dd3.Value;
% don't return until selections have been made and fig is closed
uiwait(fig);
function vcf_dd1(~,~)
switch dd1.Value
case 2
dd3.Visible = 'on';
otherwise
dd3.Visible = 'off';
end
end
function bpf_btn(~,~)
% update outputs
name = txtbox1.Value;
dd1_option = dd1.Value;
dd2_option = dd2.Value;
dd3_option = dd3.Value;
% close the figure
close(fig);
end
end

6 Comments

Thanks for the help, you guys are quick and very accurate so thanks so much. Functions are not very clear to me right now, its turning out to be much more difficult to learn than regular popup messages like ive been doing.
Im still trying to learn about functions so my question is why cant I create a variable without a function? I have about 500 lines of code in my original file that calculate surfaces and apply smoothing iterations are a few other things like exporting, how would I go about integrating all of that into the uifigure? Does each thing need to go into its own function? Depending on the value from the drop down a different suite of math takes place, I had a tough time integrating any of that in the app builder. Theres a steep learning curve here, thanks again for your help.
I add Surface_Options to the top of my other matlab code and the uifigure opens up, I then commented out all the stuff in that code but I cant get a variable in the original code to update once the button is pressed.
I made another variable called Figure_Output = dd1_options then disp(Figure_Output) and nothing happened. I tried again with disp(dd1_options) and again, nothing. Im not quite sure I understand how to call this function in my original code. Any idea how to get dd1_options to update in my original code? Hints or tips are appreciated. Thank you.
You're welcome!
"why cant I create a variable without a function?"
You definitely can create a variable without a function; in scripts, for instance, that's what happens.
"Does each thing need to go into its own function?"
Typically in a GUI, any time you want something to happen when you interact with a UI component, e.g., click a button, change a dropdown selection, etc., and you want the action to take place immediately, you'll use a function to do that. The function is the callback (ButtonPushedFcn, ValueChangedFcn, etc.) of that component, as vf_dd1 and bpf_btn are the callbacks of the dd1 dropdown and btn button, respectively, in the code in my answer.
More generally, a function is a piece of code that is intended to perform a specific task. Generally a function takes some input(s), does something with the input(s), and returns some output(s) based on what it did. Any time you need to do the same thing on different inputs or in different contexts, having a function that does it is a good idea. (Callback functions in a GUI don't return outputs but they do do specific tasks; vcf_dd1 sets the visibility of dd3 based on dd1's Value, and that's all it does - a very narrow and specific task, and that's good.)
I imagined the purpose of the GUI you're writing now was to take a few selections from the user and use them in subsequent processing, e.g., in a separate script or function the GUI is called from; that's why I wrote my answer to return outputs corresponding to the user's selections.
However, if your intention is to write something self-contained, where the selections update plots or whatever inside the GUI itself, then your main function should not typically return any outputs and you don't need to use uiwait or have the OK button. That would be more like a typical self-contained GUI application (as opposed to a dialog for gathering and returning selections), and the code would look like this:
function Surface_GUI()
fig = uifigure("Name", 'Single Beam Processing', 'Position', [30,75,1450,750]);
panel1 = uipanel(fig, "Position", [50,350,200,350]);
panel1.Title = "Program Setup";
panel1.TitlePosition = 'centertop';
panel1.FontSize = 14;
txtbox1 = uieditfield(panel1,"Text", "Position", [10,290,180,30], "Value", "Operator Name");
dd1 = uidropdown(panel1, 'Position', [10,250,180,30], 'ValueChangedFcn', @vcf_dd1);
dd1.Items = ["Choose Surface Type", "Depth", "Calculated Surface", "Fitted Plane", "Corrected Points", "None"];
dd1.ItemsData = [0 1 2 3 4 5];
dd1.Visible = 'on';
dd2 = uidropdown(panel1, 'Position', [10,210,180,30]);
dd2.Items = ["Choose Save Options", "Save as CSV", "Save as txt"];
dd2.ItemsData = [0 1 2];
dd1.Visible = 'on';
dd3 = uidropdown(panel1, 'Position', [10,170,180,30]);
dd3.Items = ["Choose Smoothing Type", "Lowess", "Cubic Interpolation"];
dd3.ItemsData = [0 1 2];
dd3.Visible = 'off';
function vcf_dd1(~,~)
switch dd1.Value
case 2
dd3.Visible = 'on';
otherwise
dd3.Visible = 'off';
end
end
end
At the moment the only thing that does is create the uifigure window and the UI components, and when dd1's Value changes dd3's visibility is updated. You can build on it from there, adding components and functionality. Again, any component that needs to do something immediately needs a callback function. Some components may not have a callback function; it all depends on how you want it to work. For example, an update button might update plots based on selections made in checkboxes and dropdowns, in which case the update button has a callback but the checkboxes and dropdowns do not because nothing updates until you click the update button; or you can have the plots update immediately when a checkbox or dropdown is interacted with, in which case they will have callbacks and you can do away with the update button entirely. The design is up to the programmer.
One final note: I used nested functions in my answer (the vf_dd1 and bpf_btn callbacks are nested inside the main function Surface_Options). In my opinion nested functions are a very convenient way to develop GUIs programmatically because they make sharing data between the main function and the callbacks easy (it happens just by virtue of the callbacks being nested in the main function).
"I add Surface_Options to the top of my other matlab code and the uifigure opens up, I then commented out all the stuff in that code but I cant get a variable in the original code to update once the button is pressed.
I made another variable called Figure_Output = dd1_options then disp(Figure_Output) and nothing happened. I tried again with disp(dd1_options) and again, nothing. Im not quite sure I understand how to call this function in my original code. Any idea how to get dd1_options to update in my original code?"
I would need to see the code.
And also I'd need to know what your intent is with this GUI, i.e., is it going to be a self-contained application or a dialog window for collecting a few inputs for subsequent use by other code?
Thanky ou again for the detailed response, it was incredibly helpful. I was able to get the calculations I want to run by adding them into the bpf_btn function. Once the button is clicked it runs the calculations and plots my data. Thanks again!

Sign in to comment.

More Answers (0)

Categories

Find more on Develop Apps Programmatically in Help Center and File Exchange

Products

Release

R2023b

Tags

Asked:

on 20 Mar 2024

Commented:

on 21 Mar 2024

Community Treasure Hunt

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

Start Hunting!