GUI with two popup menus

8 views (last 30 days)
kanimbla
kanimbla on 1 Sep 2014
Commented: kanimbla on 4 Sep 2014
Dear all,
I am new to GUI programming and I have tried to figure out for some time how to use two popup menus in a GUI.
Suppose popup menu 1 specifies a set of countries and popup menu 2 specifies a set of variables common to all countries. I would like to plot all possible country/variable pairs.
Below I show my code which does not work (potentially also because I do not appropriately pass the data between functions "popup_menu1_Callback" and "popup_menu2_Callback").
Any hints or suggestions would be great, many thanks!
Here is the example-code:
function example_gui
% SIMPLE_GUI2 Select a data set from the pop-up menu, then
% click one of the plot-type push buttons. Clicking the button
% plots the selected data in the axes.
% Create and then hide the GUI as it is being constructed.
f = figure('Visible','off','Position',[260,500,800,485]);
% Construct the components.
hplot = uicontrol('Style','pushbutton','String','Figure','Position',[615,420,100,25],'Callback',{@plot_Callback});
hpopup = uicontrol('Style','popupmenu','String',{'US','Japan'},'Position',[615,260,100,25],'Callback',{@popup_menu1_Callback});
htext = uicontrol('Style','text','String','Country','Position',[615,300,100,15]);
gpopup = uicontrol('Style','popupmenu','String',{'GDP','Trade Balance'},'Position',[615,180,100,25],'Callback',{@popup_menu2_Callback});
gtext = uicontrol('Style','text','String','Indicator','Position',[615,220,100,15]);
ha = axes('Units','pixels','Position',[50,60,500,385]);
align([hplot,gtext,htext,hpopup,gpopup],'Center','None');
% Change units to normalized so components resize automatically.
set([hplot,gtext,htext,hpopup,gpopup],'Units','normalized');
% Generate the data to plot.
vars=evalin('base','vars') % matrix with dimesnion 4x100
% Assign the GUI a name to appear in the window title.
set(f,'Name','Simple GUI')
% Move the GUI to the center of the screen.
movegui(f,'center')
% Make the GUI visible.
set(f,'Visible','on');
function popup_menu1_Callback(hObject,source,eventdata)
global data
% Determine the selected data set.
str = get(hObject, 'String');
val = get(hObject, 'Value');
% Set current data to the selected data set.
switch str{val};
case 'US'
data = vars(1:2,:)
case 'Japan'
data = vars(3:4,:)
end
end
function popup_menu2_Callback(hObject,source,eventdata)
global data
% Determine the selected data set.
str = get(hObject, 'String');
val = get(hObject, 'Value');
% Set current data to the selected data set.
switch str{val};
case 'GDP'
data = data(1,:)
case 'Trade Balance'
data = data(2,:)
end
end
function plot_Callback(source,eventdata)
plot(data);
end
end
  2 Comments
Stephen23
Stephen23 on 4 Sep 2014
kanimbla: If someone has written an answer that solves your problem, then it would be polite to "accept" it... I am sure that this would be appreciated.
Note that global variables are almost always a bad idea:
Instead use nested functions, and/or passing variables as inputs and outputs.
kanimbla
kanimbla on 4 Sep 2014
Fair enough,
thanks for additional comments

Sign in to comment.

Accepted Answer

Geoff Hayes
Geoff Hayes on 3 Sep 2014
kanimbla - the way your code is structured, you don't really need to use callbacks for the popup menus since nothing is plotted until the user presses the push button. I think that you can simplify your code if you just move all logic to the push button callback plot_Callback.
Because you have written your code so that all callbacks are nested functions within the example_gui main function, any local variables defined within example_gui are accessible to the nested functions. That means handles to the widgets, the vars local variable, etc. are all available to the nested function. So you can do away with global variables and do something more like
function plot_Callback(source,eventdata)
% get the country id
ctryId = get(hpopup,'Value');
% get the attribute id
attrId = get(gpopup,'Value');
% get the number of countries
numCtrs = length(get(hpopup,'String'));
% get the number of attributes
numAttrs = length(get(gpopup,'String'));
% since data the data in vars is grouped by country and by attribute
% then we can access the appropriate data using the above information
dataToPlot = vars((ctryId-1)*numAttrs + attrId,:);
plot(dataToPlot);
end
In the above, I'm assuming that the rows in the vars data is: row 1, USA GDP; row 2, USA Trade Balance; row 3, Japan GDP; and row 4, Japan Trade Balance. We access the appropriate row given the selected country (with its index in the country pop-up menu) and the selected attribute (with its index in the attribute pop-up menu).
The above should get you going. There are a couple of things to consider - try to give your local variables names that reflect more what they do. For example, instead of hpopup for the handle to the country pop-up menu, perhaps write ctryPopupHandle or something similar. As well, you can pass vars as an input to this function if you modify the signature to
function example_gui(vars)
This way you can avoid the evalin call at
vars=evalin('base','vars') % matrix with dimesnion 4x100
I left the pop-up menu callbacks in place but removed their code
function popup_menu1_Callback(hObject,source,eventdata)
% intentionally left blank
end
function popup_menu2_Callback(hObject,source,eventdata)
% intentionally left blank
end
There is no need for them to do anything (currently) since the push button callback is doing the majority/all of the work.
Try the above and see what happens!

More Answers (1)

kanimbla
kanimbla on 4 Sep 2014
Exactly the solution I was looking for as it can be applied to more than two popup menus and a larger set of popup entries. Good point also regarding the evalin call.
Thanks a lot!

Categories

Find more on Matrices and Arrays in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!