Reading cases from a file - matlab

I have different cases resulting from my popupmenu. However, I would like to have a some sort of file (for example .mat) where the cases are read from (in for example a for loop?). How is this is possible to implement?
% --- Executes on selection change in hd_poweramp.
function hd_poweramp_Callback(hObject, eventdata, handles)
% hObject handle to hd_poweramp (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
val = get(hObject, 'Value');
str = get(hObject, 'String');
switch str{val}
case '325LA Precision Acoustics'
if handles.transducer_index == 1;
handles.fgen1_voltage = (handles.fgen1_PNP*2-28.8)/0.72; % Double check that
else if handles.transducer_index == 2;
handles.fgen1_voltage = (handles.fgen1_PNP*2-28.8)/6.055; % Double check that
end
end
case '2100L E&I'
if handles.transducer_index == 1;
handles.fgen1_voltage = (handles.fgen1_PNP*2-10.267)/1.6; % Double check that
else if handles.transducer_index == 2;
handles.fgen1_voltage = (handles.fgen1_PNP*2-28.8)/6.055; % Double check that
end
end
end
guidata(hObject, handles); % Update the GUI data structure

You can store your data in a uniform structure and use that to generate your dropdown selections and drive the calculations.
Consider the following example GUI (full code at the bottom):
Here are the 2 most relevant sections:
function makedummydata(mydatafile)
cases(1).Name = '325LA Precision Acoustics';
cases(1).ntransducers = 2;
cases(1).TransducerConstant1(1) = 28.8;
cases(1).TransducerConstant1(2) = 28.8;
cases(1).TransducerConstant2(1) = 0.72;
cases(1).TransducerConstant2(2) = 6.055;
cases(2).Name = '2100L E&I';
cases(2).ntransducers = 2;
cases(2).TransducerConstant1(1) = 10.267;
cases(2).TransducerConstant1(2) = 28.8;
cases(2).TransducerConstant2(1) = 1.6;
cases(2).TransducerConstant2(2) = 6.055;
save(mydatafile, 'cases');
end
And
function recalc(hObj, ~)
handles = guidata(hObj);
deviceID = handles.devicedd.Value;
transducerID = handles.transducerdd.Value;
fgen1_PNP = str2double(handles.fgen1_PNP.String);
TransducerConstant1 = handles.UserData(deviceID).TransducerConstant1(transducerID);
TransducerConstant2 = handles.UserData(deviceID).TransducerConstant2(transducerID);
voltage = (fgen1_PNP*2 - TransducerConstant1)/TransducerConstant2;
handles.resultsbox.String = voltage;
end
Here I've created an array of structures where each top level index corresponds to a device and its relevant constants. When the GUI is generated, the dropdown list is populated with all of the device names and the transducer list is populated with the number of transducers available for the device.
When you make changes to either one of the dropdowns or the fgen1 PNP, the voltage is recalculated. Note how simple the recalculation function is. Because we set up our data structure in a MATLAB-ic way, we can easily access all of the relevant portions without requiring loops, string manipulations, or the dreaded eval.
Full GUI code:
function testcode
% Set up sample data
mydatafile = 'mydevices.mat';
makedummydata(mydatafile);
buildGUI(mydatafile);
end
function recalc(hObj, ~)
handles = guidata(hObj);
deviceID = handles.devicedd.Value;
transducerID = handles.transducerdd.Value;
fgen1_PNP = str2double(handles.fgen1_PNP.String);
TransducerConstant1 = handles.UserData(deviceID).TransducerConstant1(transducerID);
TransducerConstant2 = handles.UserData(deviceID).TransducerConstant2(transducerID);
voltage = (fgen1_PNP*2 - TransducerConstant1)/TransducerConstant2;
handles.resultsbox.String = voltage;
end
function makedummydata(mydatafile)
cases(1).Name = '325LA Precision Acoustics';
cases(1).ntransducers = 2;
cases(1).TransducerConstant1(1) = 28.8;
cases(1).TransducerConstant1(2) = 28.8;
cases(1).TransducerConstant2(1) = 0.72;
cases(1).TransducerConstant2(2) = 6.055;
cases(2).Name = '2100L E&I';
cases(2).ntransducers = 2;
cases(2).TransducerConstant1(1) = 10.267;
cases(2).TransducerConstant1(2) = 28.8;
cases(2).TransducerConstant2(1) = 1.6;
cases(2).TransducerConstant2(2) = 6.055;
save(mydatafile, 'cases');
end
function buildGUI(mydatafile)
% Generate GUI
h.f = figure('MenuBar', 'none', 'ToolBar', 'none', 'NumberTitle', 'off');
cases = load(mydatafile, 'cases');
h.UserData = cases.cases; % Remove extra layer
h.lbl(1) = uicontrol('Parent', h.f, 'Style', 'Text', ...
'Units', 'Normalized', 'Position', [0.1 0.7 0.6 0.1], ...
'FontSize', 12, 'HorizontalAlignment', 'left', 'String', 'Device Thing');
h.devicedd = uicontrol('Parent', h.f, 'Style', 'popupmenu', ...
'Units', 'Normalized', 'Position', [0.1 0.55 0.6 0.2], ...
'String', {h.UserData(:).Name}, 'Callback', #recalc);
h.lbl(2) = uicontrol('Parent', h.f, 'Style', 'Text', ...
'Units', 'Normalized', 'Position', [0.1 0.5 0.6 0.1], ...
'FontSize', 12, 'HorizontalAlignment', 'left', 'String', 'Transducer Thing');
h.transducerdd = uicontrol('Parent', h.f, 'Style', 'popupmenu', ...
'Units', 'Normalized', 'Position', [0.1 0.35 0.6 0.2], ...
'String', 1:h.UserData(1).ntransducers, 'Callback', #recalc);
h.lbl(3) = uicontrol('Parent', h.f, 'Style', 'Text', ...
'Units', 'Normalized', 'Position', [0.1 0.3 0.3 0.1], ...
'FontSize', 12, 'HorizontalAlignment', 'left', 'String', 'fgen1 PNP Thing');
h.fgen1_PNP = uicontrol('Parent', h.f, 'Style', 'edit', ...
'Units', 'Normalized', 'Position', [0.1 0.25 0.25 0.1], ...
'String', 1);
h.lbl(4) = uicontrol('Parent', h.f, 'Style', 'Text', ...
'Units', 'Normalized', 'Position', [0.5 0.3 0.3 0.1], ...
'FontSize', 12, 'HorizontalAlignment', 'left', 'String', 'Result');
h.resultsbox = uicontrol('Parent', h.f, 'Style', 'edit', ...
'Units', 'Normalized', 'Position', [0.5 0.25 0.25 0.1]);
guidata(h.f, h);
recalc(h.f, 'hi'); % Fire first calc
end

Related

MATLAB GUI: how to update handles when new objects are created in a subfunction?

I have a problem with my MATLAB GUI.
I am not using GUIDE so I am self coding everything for my GUI. I have a Main which generates the a first panel of the GUIDE. This panel contains a button which can create other 2 panels through its related callback function. In the other 2 panels it is possible to do other operations calling other callback functions. One of these operations is to create 2 new static texts and 2 new editable texts. I have problems in updating the handles related to those editable texts. More precisely I am not able to retrieve the value of their string once the text is edited and the callback functions of the last 2 panels are called again.
Attached is the code where all the callback functions of the GUI are:
%% server_selected callback function
function server_selected(hObject, eventdata, handles)
%UNTITLED8 Summary of this function goes here
% Detailed explanation goes here
% Get server version and run LaunchCDbQuery
servers = get(handles.server_popup, 'String');
serverVersion = servers{get(handles.server_popup, 'Value')};
[Day] = LaunchCDbQuery(serverVersion);
assignin('base', 'Day', Day)
% Update current outing on GUI
set(handles.outing_text, 'String', strcat(Day.date, Day.DocumentKey))
% Tool description
% Create panel for the tool description
handles.description_panel = uipanel('Title', 'Tool description',...
'units', 'normalized',...
'position', [0.675, 0.025, 0.3, 0.9]);
% Create items inside the panel for the tool description
% Function heading
handles.funheading_text = uicontrol('Parent', handles.description_panel,...
'Style', 'text',...
'units', 'normalized',...
'position', [0, 0.7, 1, 0.2],...
'String', 'Please choose a tool and click description to obtain the tool''s heading and description.',...
'HorizontalAlignment', 'left');
% Function description
handles.description_text = uicontrol('Parent', handles.description_panel,...
'Style', 'text',...
'units', 'normalized',...
'position', [0, 0.05, 1, 0.6],...
'HorizontalAlignment', 'left');
% Tool selection
% Create panel for the tool selection
handles.tool_panel = uipanel('Title', 'Tool selection',...
'units', 'normalized',...
'position', [0.35 0.025 0.3 0.9]);
% Create items inside the panel for the tool selection
% Text
handles.tool_text = uicontrol('Parent', handles.tool_panel,...
'Style', 'text',...
'units', 'normalized',...
'position', [0 0.7 1 0.2],...
'String', 'Please choose a tool to perform a piece of analysis.',...
'HorizontalAlignment', 'left');
% Popup
handles.tool_popup = uicontrol('Parent', handles.tool_panel,...
'Style', 'popup',...
'units', 'normalized',...
'position', [0.2 0.25 0.6 0.4],...
'String', {'plotmaptg'; 'TestReview'});
% Input variables panel
handles.varin_panel = uipanel('Parent', handles.tool_panel,...
'Title', 'Type input variables',...
'units', 'normalized',...
'position', [0, 0, 1, 0.3]);
% Description push
handles.tool_push_description = uicontrol('Parent', handles.tool_panel,...
'Style', 'pushbutton',...
'units', 'normalized',...
'position', [0.05 0.4 0.4 0.1],...
'String', 'Description',...
'callback', {#tool_description, handles});
% Ok push
handles.tool_push_ok = uicontrol('Parent', handles.tool_panel,...
'Style', 'pushbutton',...
'units', 'normalized',...
'position', [0.51 0.4 0.4 0.1],...
'String', 'Ok',...
'callback', {#tool_selected, handles, Day});
% Update guidata
guidata(hObject, handles)
end
%% tool_description callback function
function tool_description(hObject, eventdata, handles)
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
% Call handles function
handles = tool_description_handles(handles);
% Update guidata
guidata(hObject, handles)
end
function newHandles = tool_description_handles(handles)
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
% Get tool name
tools = get(handles.tool_popup, 'String');
tool_selected = tools{get(handles.tool_popup, 'Value')};
% Open tool .m file
fid = fopen(strcat(tool_selected, '.m'), 'r');
% Read .m file to find function description and save it
line = fgets(fid);
heading = line;
while isempty(regexp(line, '%', 'ONCE'))
line = fgets(fid);
end
description = [];
while ~isempty(regexp(line, '%', 'ONCE'))
description = strcat(description, line(regexp(line, '%', 'ONCE'):end));
line = fgets(fid);
end
description(regexp(description, '%')) = [];
fclose(fid);
% Set descritption found to the description handle
set(handles.funheading_text, 'String', heading);
set(handles.description_text, 'String', description);
% Find the input variables needed to run the tool
global inputs varout
[varin, varout] = get_arg_names(strcat(pwd, '\Tools\', tool_selected, '.m'));
inputs = cell(1, length(varin{1,1}));
for i = 1:length(varin{1,1})
% Input variable text
handles.varin_text(i) = uicontrol('Parent', handles.varin_panel,...
'Style', 'text',...
'units', 'normalized',...
'position', [0, 1-i*(1/length(varin{1,1})), 0.45, 1/length(varin{1,1})],...
'String', varin{1,1}{i,1},...
'HorizontalAlignment', 'left');
% Input variables editable text
handles.varin_edit(i) = uicontrol('Parent', handles.varin_panel,...
'Style', 'edit',...
'units', 'normalized',...
'position', [0.55, 1-i*(1/length(varin{1,1})), 1, 1/length(varin{1,1})],...
'HorizontalAlignment', 'left',...
'callback', {#varin_callback, handles});
end
% Save handles
newHandles = handles;
end
function varin_callback(hObject, eventdata, handles)
% hObject handle to edit1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Save in the main workspace the input variables
global inputs
for i = 1:length(inputs)
if isempty(inputs{1,i})
inputs{1,i} = get(hObject,'String');
break
end
end
end
%% tool_selected callback function
function tool_selected(hObject, eventdata, handles, Day)
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
% Get tool name
tools = get(handles.tool_popup, 'String');
tool = tools{get(handles.tool_popup, 'Value')};
% fh = str2func(tool);
% Get tool inputs and outputs
global inputs varout
% Run the tool
if ~isempty(varout)
expression = strcat('out = ', tool, '(');
else
expression = strcat(tool, '(');
end
for i = 1:length(inputs)
if ~isempty(inputs{1,i})
expression = strcat(expression, inputs{1,i}, ',');
else
break
end
end
expression(end) = ')';
eval(expression)
% Update guidata
guidata(hObject, handles)
end
I have tried using guidata(hObject, handles) at the end of each function but it did not work out. As now I am using global variables to avoid the problem but I would really like to just update the handles as they are modified.
When providing an input variable to a callback function, the variable that is passed when you invoke the callback is that variable as it exists when the callback is defined. MATLAB does not know to update these inputs as you modify guidata.
You can see this with the following example:
function testcode
h.mf = figure('Menubar', 'none', 'NumberTitle', 'off', 'ToolBar', 'none');
h.lb = uicontrol('Parent', h.mf, 'Style', 'Listbox', ...
'Units', 'Normalized', 'Position', [0.1 0.5 0.4 0.4] ...
);
h.b1 = uicontrol('Parent', h.mf, 'Style', 'pushbutton', ...
'Units', 'Normalized', 'Position', [0.1 0.1 0.4 0.3], ...
'String', 'Pass handles','Callback', {#button1push, h});
h.b2 = uicontrol('Parent', h.mf, 'Style', 'pushbutton', ...
'Units', 'Normalized', 'Position', [0.5 0.1 0.4 0.3], ...
'String', 'Use GUIdata', 'Callback', #button2push);
guidata(h.mf, h);
makepanel(h.mf);
end
function makepanel(mf)
h = guidata(mf);
h.panel = uipanel('Parent', h.mf, 'Title', 'A Panel', ...
'Units', 'Normalized', 'Position', [0.5 0.5 0.4 0.4] ...
);
guidata(h.mf, h);
end
function button1push(~, ~, h)
h.lb.String = fieldnames(h);
end
function button2push(hObj, ~)
h = guidata(hObj);
h.lb.String = fieldnames(h);
end
Push each button and look at the output in the listbox. You can see that the change to h made in makepanel is not shown when you hit Button 1.
Rather than passing handles as a callback input (like Button 1 above), call guidata with an output at the beginning of your function to obtain the most current version of handles. If your callback makes changes to the handles structure, call guidata again to store these changes for other callbacks.

uicontrol callback for more than one function

I want to write a GUI program in Matlab and make 3 sliders on it with uicontrol and then write callbacks to use their 3 values in one command. I found a way to write a function for one slider as you can see in my program. Can you help me how use these 3 callbacks? (I use R2014a)
sld = uicontrol('Style', 'slider',...
'Min',0,'Max',255,'Value',0,...
'Position', [400 20 120 20],...
'Callback', #Blue);
sld = uicontrol('Style', 'slider',...
'Min',0,'Max',255,'Value',0,...
'Position', [400 60 120 20],...
'Callback', #Green);
sld = uicontrol('Style', 'slider',...
'Min',0,'Max',255,'Value',255,...
'Position', [400 100 120 20],...
'Callback', #Red);
function Red(source,~)
R = get(source,'Value');
end
function Green(source,~)
G = get(source,'Value');
end
function Blue(source,~)
B = get(source,'Value');
end
RGB = cat(3,R,G,B); %??????
Error: Undefined function or variable "R".
Persistent data must be stored somewhere that's accessible to the callback function. One common technique is to use the parent figure's UserData field. In the example above, once a slider has been moved, the current colour can be found in the RGB field of figure fh's UserData. Also, here only one callback is used, and the UI item is identified via its Tag.
fh = figure(1);
clf
%// Initialize figure's UserData
set(fh, 'UserData', struct('RGB', [0 0 0]));
sld_b = uicontrol('Style', 'slider',...
'Min',0,'Max',255,'Value',0,...
'Position', [400 20 120 20],...
'Callback', #colourHandler, 'Tag', 'blue');
sld_g = uicontrol('Style', 'slider',...
'Min',0,'Max',255,'Value',0,...
'Position', [400 60 120 20],...
'Callback', #colourHandler, 'Tag', 'green');
sld_r = uicontrol('Style', 'slider',...
'Min',0,'Max',255,'Value',255,...
'Position', [400 100 120 20],...
'Callback', #colourHandler, 'Tag', 'red');
%// This is in a separate file, colourHandler.m
function colourHandler(source, ~)
%// Find which slider triggered us
if strcmpi(get(source, 'Tag'), 'red')
ind = 1;
elseif strcmpi(get(source, 'Tag'), 'green')
ind = 2;
else
ind = 3;
end
%// update UserData
ud = get(get(source, 'Parent'), 'UserData');
ud.RGB(ind) = get(source, 'Value');
set(get(source, 'Parent'), 'UserData', ud);
end
Alternatively you can just store the handles of your graphics objects and use those to obtain the values in other functions.
For example:
function testcode
% Initialize sample GUI
h.fig = figure( 'MenuBar', 'none', 'ToolBar', 'none');
h.sld(1) = uicontrol( ...
'Parent', h.fig, ...
'Style', 'slider',...
'Min', 0, 'Max', 255, 'Value', 0, ...
'Units', 'Normalized', 'Position', [0.1 0.65 0.4 0.1], ...
'Tag', 'Red' ...
);
h.sld(2) = uicontrol( ...
'Parent', h.fig, ...
'Style', 'slider', ...
'Min', 0, 'Max', 255, 'Value', 0, ...
'Units', 'Normalized', 'Position', [0.1 0.45 0.4 0.1], ...
'Tag', 'Green' ...
);
h.sld(3) = uicontrol( ...
'Parent', h.fig, ...
'Style', 'slider', ...
'Min', 0, 'Max', 255, 'Value', 255, ...
'Units', 'Normalized', 'Position', [0.1 0.25 0.4 0.1], ...
'Tag', 'Blue' ...
);
% Use an axes object as a color display box
% Get starting RGB values for the color display, normalized so 0 <= x <= 1
startRGB = [get(h.sld(1), 'Value'), get(h.sld(2), 'Value'), get(h.sld(3), 'Value')]/255;
h.ax = axes( ...
'Parent', h.fig, ...
'Units', 'Normalized', 'Position', [0.6 0.36 0.3 0.3], ...
'XTickLabels', '', 'YTickLabels', '', ...
'Color', startRGB ...
);
% Need to set callback after all our elements are initialized
nsliders = length(h.sld);
set(h.sld, {'Callback'}, repmat({{#slidercallback, h}}, nsliders, 1));
end
function slidercallback(~, ~, h)
% Update background color of our axes object every time the slider is updated
RGB = [get(h.sld(1), 'Value'), get(h.sld(2), 'Value'), get(h.sld(3), 'Value')]/255;
set(h.ax, 'Color', RGB');
end
When callbacks execute they are passed 2 inputs by default, the invoking object and a structure of event data. As explained in the callback documentation, you can pass additional inputs to your callback by wrapping everything into a cell array. One thing to note is that the value of your variable being passed to the callback is its value as it exists when you define the callback. In other words, if we set the callback for our sliders at the same time we create them, when the callback for Red is fired h will only contain a handle to our figure, when the callback for Green is fired h will contain a handle to our figure and to the Red slider, and so on.
Because of this, you will see I have defined the callbacks once we have initialized all of our graphics objects. Using the curly brackets to set properties of multiple objects is explained in MATLAB's documentation for set. I use repmat so the size of the cell array is the same size as our array of slider objects.

MATLAB: How to pass data between 2 GUIs using the findobj-Function?

i am new to creating GUIs with Matlab. I have one MainGui from which i open a Subgui so that the user can click checkboxes. After clicking the okay-Button my Subgui closes and one sees the MainGui-surface again.
How can i access the clickbutton value without using getappdata and setappdata and instead doing it with findobj-function which when it works is far easier for me.
So i am in the MainGui code and i look for the Subgui with
hGui = findobj('Tag','Subgui');
where 'Subgui' is the value of the Tag property of the SubGUI. Handles visibility is on for both!!
% get control handles for this GUI
handlesSubgui = guidata(hGui);
% now read the data from the checkbox
checkValue = get(handlesSubgui.checkbox1,'Value');
Why doesnt it work? i set the correct Tags and handle visilility is on but i get
hGui =
Empty matrix: 0-by-1
!?
Has anyone an idea? i would be glad to get help!
Best regards, John
One option to consider for a case like this is to initialize a small GUI inside your button callback. To illustrate, I'll set up a little programmatic GUI:
function testcode
res = get(0,'ScreenSize');
figdim = [300 300]; % Figure size, pixels
h.mainfig = figure( ...
'Units', 'Pixels', ...
'Position', [(res(3) - figdim(1))/2 (res(4) - figdim(2))/2 figdim(1) figdim(2)], ...
'Name', 'This is the Main GUI', ...
'Resize', 'off', ...
'DockControls', 'off', ...
'NumberTitle', 'off', ...
'MenuBar', 'none', ...
'Toolbar', 'none' ...
);
h.subGUIbutton = uicontrol( ...
'Parent', h.mainfig, ...
'Units', 'Normalized', ...
'Position', [0.25 0.6 0.5 0.3], ...
'String', 'Open Checkbox GUI' ...
);
h.displaydatabutton = uicontrol( ...
'Parent', h.mainfig, ...
'Units', 'Normalized', ...
'Position', [0.25 0.1 0.5 0.3], ...
'String', 'Display Checkbox Selections' ...
);
% Requires R2014b or newer, otherwise we'll have to use set
try
h.subGUIbutton.Callback = {#checkboxGUI, h};
h.displaydatabutton.Callback = {#displaydata, h};
catch
set(h.subGUIbutton, 'Callback', {#checkboxGUI, h});
set(h.displaydatabutton, 'Callback', {#displaydata, h});
end
And our callbacks will be structured like this:
function checkboxGUI(~, ~, handles)
res = get(0,'ScreenSize');
figdim = [200 200]; % Figure size, pixels
h2.mainfig = figure( ...
'Units', 'Pixels', ...
'Position', [(res(3) - figdim(1))/2 (res(4) - figdim(2))/2 figdim(1) figdim(2)], ...
'Name', 'This is the Sub GUI', ...
'Resize', 'off', ...
'DockControls', 'off', ...
'NumberTitle', 'off', ...
'MenuBar', 'none', ...
'Toolbar', 'none' ...
);
% Build some checkboxes
for ii = 1:4
h2.checkbox(ii) = uicontrol( ...
'Parent', h2.mainfig, ...
'Style', 'checkbox', ...
'Units', 'Normalized', ...
'Position', [0.25 (1 - ii*0.15) 0.5 0.1], ...
'String', sprintf('Checkbox #%u', ii) ...
);
end
h2.closebutton = uicontrol( ...
'Parent', h2.mainfig, ...
'Style', 'pushbutton', ...
'Units', 'Normalized', ...
'Position', [0.25 0.15 0.5 0.1], ...
'String', 'Accept Changes', ...
'Callback', {#closecheckbox} ...
);
function closecheckbox(~, ~)
% requires R2014b or newer for dot notation
try
test = find([h2.checkbox(:).Value]); % Returns ID of checked boxes
catch
test = find(cell2mat(get(h2.checkbox(:), 'Value'))'); % Returns ID of checked boxes
setappdata(handles.mainfig, 'BoxesChecked', test);
close(h2.mainfig);
end
waitfor(h2.mainfig); % Wait for user to close the checkbox GUI
end
function displaydata(~, ~, handles)
BoxesChecked = getappdata(handles.mainfig, 'BoxesChecked');
if isempty(BoxesChecked)
fprintf('No boxes celected\n');
else
fprintf('User selected box: %d\n', BoxesChecked);
end
end
Note that I've used a nested function for readability. In this simple example we have two buttons in our main GUI, a button to open the user prompt and then a display button. When the user opens the checkbox prompt, execution of all GUI commands pauses until the prompt is closed. When the display button is clicked, we get the checked values from the app data and print them to the command window.

Different settings using GUI pop-up button (matlab)

So I've been working on this GUI for a while, and recently finished a prototype where you could input resistance, inductance, and capacitance to get the quality factor, and the resonance frequency using equations. What I want to do now is to make a GUI that accepts different sets to find the missing values. ex: given q-factor, resistance, and inductance. I've made a pop-up button that I want to switch depending on what the user has to input. I'm new to GUI programming, so I was wondering if making a giant If statement following the pop-up button is the simplest way. ex: if (RCL)... if(QLR)... of course this would make me type out tons of code for each setting, so I was wondering if there was an easier way. Thanks in advance.
In my gui I have 5 edit text boxes, a popup button, and a graph. what I want to happen is for the user to choose which setting they have depending on the inputs that they have, and for the remaining edit boxes to display the other values. so if they select the RCL setting, I want the program to take the RCL inputs, and calculate W and Q, then show them in the proper edit text boxes. I want this to be malleable though, so I have made several other settings such as CLW or QRL that the user can choose from, so they can get the missing variables. the graph will be a bode plot of a transfer function using the RCL values. the main problem is that for each setting, different forms of the same equation are used to calculate the missing values. Is there a way to call the function I need for a specific case and get the values everywhere I need them?
I'm still not 100% following what you're looking for, but hopefully this gets you going in the right direction:
function testGUI
% Initialize dummy GUI
h.mainwindow = figure( ... % Main figure window
'Units','pixels', ...
'Position',[100 100 400 400], ...
'MenuBar','none', ...
'ToolBar','none', ...
'Resize', 'off' ...
);
h.var1box = uicontrol( ...
'Parent', h.mainwindow, ...
'Style', 'edit', ...
'Units', 'Normalized', ...
'Position', [0.4 0.5 0.2 0.1], ...
'String', '0' ...
);
h.var2box = uicontrol( ...
'Parent', h.mainwindow, ...
'Style', 'edit', ...
'Units', 'Normalized', ...
'Position', [0.4 0.3 0.2 0.1], ...
'String', '0' ...
);
h.var3box = uicontrol( ...
'Parent', h.mainwindow, ...
'Style', 'edit', ...
'Units', 'Normalized', ...
'Position', [0.4 0.1 0.2 0.1], ...
'String', '', ...
'Enable', 'off' ...
);
h.var1label = uicontrol( ...
'Parent', h.mainwindow, ...
'Style', 'text', ...
'Units', 'Normalized', ...
'Position', [0.4 0.6 0.2 0.05], ...
'String', 'Var1' ...
);
h.var2label = uicontrol( ...
'Parent', h.mainwindow, ...
'Style', 'text', ...
'Units', 'Normalized', ...
'Position', [0.4 0.4 0.2 0.05], ...
'String', 'Var2' ...
);
h.var3label = uicontrol( ...
'Parent', h.mainwindow, ...
'Style', 'text', ...
'Units', 'Normalized', ...
'Position', [0.4 0.2 0.2 0.05], ...
'String', 'Var3' ...
);
h.dropdown = uicontrol( ...
'Parent', h.mainwindow, ...
'Style', 'popupmenu', ...
'Units', 'Normalized', ...
'Position', [0.3 0.7 0.4 0.05], ...
'String', {'Var1'; 'Var2'; 'Var3'}, ...
'Value', 3, ...
'Callback', {#vartoggle, h} ...
);
h.dropdownlabel = uicontrol( ...
'Parent', h.mainwindow, ...
'Style', 'text', ...
'Units', 'Normalized', ...
'Position', [0.3 0.75 0.4 0.05], ...
'String', 'Variable to solve for?' ...
);
h.calculatebutton = uicontrol( ...
'Parent', h.mainwindow, ...
'Style', 'pushbutton', ...
'Units', 'Normalized', ...
'Position', [0.72 0.7 0.2 0.05], ...
'String', 'Calculate', ...
'Callback', {#calcdata, h} ...
);
end
function vartoggle(eventdata, ~, h)
% Execute on change in dropdown menu, enable/disable edit boxes
% appropriately
switch eventdata.Value
case 1
% Solve for variable 1
h.var1box.Enable = 'off';
h.var2box.Enable = 'on';
h.var3box.Enable = 'on';
h.var1box.String = '';
h.var2box.String = '0';
h.var3box.String = '0';
case 2
% Solve for variable 2
h.var1box.Enable = 'on';
h.var2box.Enable = 'off';
h.var3box.Enable = 'on';
h.var1box.String = '0';
h.var2box.String = '';
h.var3box.String = '0';
case 3
% Solve for variable 3
h.var1box.Enable = 'on';
h.var2box.Enable = 'on';
h.var3box.Enable = 'off';
h.var1box.String = '0';
h.var2box.String = '0';
h.var3box.String = '';
end
end
function calcdata(~, ~, h)
% Execute when calculate button is pressed, calculate missing value
% Asssumes Var1 + Var2 = Var 3 for this example
switch h.dropdown.Value
case 1
% Solve for variable 1
B = str2double(h.var2box.String);
C = str2double(h.var3box.String);
A = C - B;
h.var1box.String = A;
case 2
% Solve for variable 2
A = str2double(h.var1box.String);
C = str2double(h.var3box.String);
B = C - A;
h.var2box.String = B;
case 3
% Solve for variable 3
A = str2double(h.var1box.String);
B = str2double(h.var2box.String);
C = A + B;
h.var3box.String = C;
end
end
What this does is allow the user to specify the quantity to solve for and updates your ability to modify the edit boxes accordingly. Once you click the calculate button the missing value is calculated.

Interrupting/Disabling ROI drawing functions in a GUI

I am programming a GUI for the selection of regions of interest (ROIs) in an image.
Several kinds of regions may be chosen using built-in MATLAB functions such as impoly/imellipse.
Below, I provide a minimal working example of a GUI where my problem may be addressed.
The question is: supposing one user misclicks one of the ROI selection buttons (i.e. chooses to select an Ellipse when the goal was to select a Polygon) how can I cancel the interactive tool for the ROI selection AVOIDING errors in the workspace?
I know that pressing the "Esc" key cancels the interactive tool but I would like to avoid errors.
One idea is to have another push button (Abort) to perform the interruption but I've been unable to come up with code to perform this operation.
function roiData = testGUI(sourceImage)
% Initialize main figure
hdl.mainfig = figure();
% Initialize roiData and roiCounter
roiData = [];
roiCounter = 0;
% Select Elliptical ROI button
hdl.selectEllipseButton = uicontrol(hdl.mainfig, 'Units', 'normalized', 'Position',[0.05 0.7 0.2 0.1], 'String', 'Select Ellipse', 'Callback', #selectEllipse);
% Select Polygonal ROI button
hdl.selectPolygonButton = uicontrol(hdl.mainfig, 'Units', 'normalized', 'Position',[0.05 0.6 0.2 0.1], 'String', 'Select Polygon', 'Callback', #selectPolygon);
% Abort Button
hdl.abort = uicontrol(hdl.mainfig, 'Units', 'normalized', 'Position',[0.05 0.2 0.2 0.2], 'String', 'Abort', 'Callback', #abort);
% Axes
hdl.axes = axes('Parent',hdl.mainfig, 'Units', 'Normalized', 'Position', [0.35 0.2 0.6 0.6]);
function selectEllipse(~, ~, ~)
imshow(sourceImage, [], 'Parent', hdl.axes);
roiCounter = roiCounter + 1;
h = imellipse(hdl.axes);
mask = uint16(createMask(h));
wait(h);
roiData(roiCounter).mask = mask;
end
function selectPolygon(~, ~, ~)
imshow(sourceImage, [], 'Parent', hdl.axes);
roiCounter = roiCounter + 1;
h = impoly(hdl.axes);
mask = uint16(createMask(h));
wait(h);
roiData(roiCounter).mask = mask;
end
function abort(~, ~, ~)
cla(hdl.axes)
% I need something else here... (see above)
end
% Pause until figure is closed
waitfor(hdl.mainfig);
end
Try this out:
function roiData = testGUI(sourceImage)
% Initialize main figure
hdl.mainfig = figure();
% Initialize roiData and roiCounter
roiData = [];
roiCounter = 0;
% Select Elliptical ROI button
hdl.selectEllipseButton = uicontrol(hdl.mainfig, 'Units', 'normalized', 'Position',[0.05 0.7 0.2 0.1], 'String', 'Select Ellipse', 'Callback', #selectEllipse);
% Select Polygonal ROI button
hdl.selectPolygonButton = uicontrol(hdl.mainfig, 'Units', 'normalized', 'Position',[0.05 0.6 0.2 0.1], 'String', 'Select Polygon', 'Callback', #selectPolygon);
% Abort Button
hdl.abort = uicontrol(hdl.mainfig, 'Units', 'normalized', 'Position',[0.05 0.2 0.2 0.2], 'String', 'Abort', 'Callback', #abort);
% Axes
hdl.axes = axes('Parent',hdl.mainfig, 'Units', 'Normalized', 'Position', [0.35 0.2 0.6 0.6]);
% Callbackrunning parameter
callbackrunning = false;
function selectEllipse(hObject,eventdata)
if(callbackrunning)
return;
end
callbackrunning = true;
imshow(sourceImage, [], 'Parent', hdl.axes);
roiCounter = roiCounter + 1;
h = imellipse(hdl.axes);
if(~callbackrunning)
return;
end
mask = uint16(createMask(h));
roiData(roiCounter).mask = mask;
callbackrunning = false;
end
function selectPolygon(hObject,eventdata)
if(callbackrunning)
return;
end
callbackrunning = true;
imshow(sourceImage, [], 'Parent', hdl.axes);
roiCounter = roiCounter + 1;
h = impoly(hdl.axes);
if(~callbackrunning)
return;
end
mask = uint16(createMask(h));
roiData(roiCounter).mask = mask;
callbackrunning = false;
end
function abort(hObject,eventdata)
if(callbackrunning)
disp('Fire escape key to cancel previous imrect');
% Create robot that fires an escape key
robot = java.awt.Robot;
robot.keyPress (java.awt.event.KeyEvent.VK_ESCAPE);
robot.keyRelease (java.awt.event.KeyEvent.VK_ESCAPE);
callbackrunning = false;
end
end
% Pause until figure is closed
waitfor(hdl.mainfig);
end
The robot object fires the escape key which cancels imrect.