Related
I have a series of lines which I would like to mark interactively (using brush). For this purpose, I tried adapting a similar code found here. However that code is not suitable for my use case because it is written with a single line in mind, whereas I have multiple lines (plotted on a single axes).
Hence, I extended the code to achieve my goal as follows:
function testbrushcode()
% Create data
t = 0:0.2:25;
x = sin(t);
y = tan(2.*t);
z = sin(2*t);
% Create figure with points
for i = 1:3
myfig = figure();
m{1} = plot(t, x);
hold on
m{2} = plot(t, y);
m{3} = plot(t, z);
hold off
brush on;
index_vec1{i} = brushed_Data_ids(myfig, m{i});
end
plot(t(index_vec1{1}), x(index_vec1{1}))
hold on
plot(t(index_vec1{2}), x(index_vec1{2}))
plot(t(index_vec1{3}), x(index_vec1{3}))
hold off
end
function [index_vec1] = brushed_Data_ids(myfig, m)
uicontrol('Parent', myfig, ...
'Style', 'pushbutton',...
'String', 'Get selected points index',...
'Position', [5, 5, 200, 30],...
'Units', 'pixels',...
'Callback', {#mycallback, m} ...
);
% ---> Now the user should select the points and click the button 'Get
% selected points index'
waitfor(myfig)
% Display index of selected points once the figure is closed
% disp(selectedPoints);
index_vec1 = [];
for i = 1:length(selectedPoints)
if selectedPoints(i) == 1
index_vec1 = [index_vec1 i];
end
end
end
function mycallback(~, ~, mylineseries)
% Ignore the first 2 function inputs: handle of invoking object & event
% data
assignin('caller', 'selectedPoints', get(mylineseries,'BrushData'))
end
There is a problem in the code stemming from using a for loop - because of it, I have to brush the same data thrice. I want to brush the data once and get the brushed indices (from the unbrushed data) for all three lines.
Try this somewhat simplified code:
function q60017140()
% Create data
t = 0:0.2:25;
x = sin(t);
y = tan(2*t);
z = sin(2*t);
% Create figure with points
hFig = figure('Position', [295,303,1014,626]);
hAx = subplot(1,2,1,'Parent', hFig);
hLines = plot(hAx, t,x, t,y, t,z);
hAx(2) = subplot(1,2,2);
uicontrol('Parent', hFig, ...
'Style', 'pushbutton',...
'String', 'Get selected points index',...
'Position', [5, 5, 200, 30],...
'Units', 'pixels',...
'Callback', {#brushCallback, hLines, hAx} ...
);
brush(hFig, 'on');
end
function brushCallback(~, ~, hLines, hAx)
index_vec = cellfun(#logical, get(hLines,'BrushData'), 'UniformOutput', false);
plot(hAx(2), ...
hLines(1).XData(index_vec{1}), hLines(1).YData(index_vec{1}), ...
hLines(2).XData(index_vec{2}), hLines(2).YData(index_vec{2}), ...
hLines(3).XData(index_vec{3}), hLines(3).YData(index_vec{3}));
end
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
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.
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.
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.