Setting default values of GUI controls using the CreateFcn

17 views (last 30 days)
Hi all,
I'm having an issue building a programmatic GUI for a small app I'm currently working on. The GUI has a number of sliders and edit boxes to modify the parameters of an aircraft which can then be further analysed. I'm trying to set the default values of those sliders and edit boxes with data from a .mat configuration file I have created separately.
I know that it's possible to set the default values of these graphics objects when you write the code to create them (ie uicontrol('Style', 'slider', 'Value', 50)), but the numbers will require some processing and given I have 40+ controls in total, it's a little impractical to do it all manually. What I'd like to do (ideally) is have a function that executes when the GUI is created that sets all the default values of all the controls then. I already have a way of updating all the parameters in an easy and scalable way but am struggling to find somewhere to execute the code. My method relies on getting the list of uicontrol objects using 'findobj' and specifying edit and slider objects, then looping through that list of returned objects and matching the tags to variable names in the configuration file. I've tested this and it seems to work well.
I thought that adding this code to the 'CreateFcn' of the GUI figure would work perfectly, as the description says this function is executed 'just before the figure is made visible' but when I run my code in this opening function 'findobj' doesn't return a list of values, just a 0x0 array. I'm guessing this is because the createFcn is executing earlier than I expected when the uicontrols haven't actually been created.
Does anyone have any ideas on how I could make this work?
Many thanks for any help,
Chris
  2 Comments
Adam
Adam on 2 Jun 2015
Edited: Adam on 2 Jun 2015
How are you creating the sliders and editboxes with their tags in the first place? It would be much better to keep an array of handles to these when you create them than rely on a load of findobj calls at a later stage.
Also where are you creating the figure? I usually do my programmatic GUIs in a class so my figure is created there and I store handles to all the components I create in the class object for later use. If I have many sliders I may store these in an array, though I usually use individually named properties. If I have functionality that requires them all I create a dependent property that puts all the slider handles into an array.
If you are creating the figure in a function can't you just call your initialisation function at the bottom of whatever function creates the figure?
Christopher Dadswell
Christopher Dadswell on 3 Jun 2015
I've created a lot of the sliders/edit boxes in for loops to quickly populate long lists of parameters without the need for the same code over and over again. This kinda lent itself to not defining definite handles and just assigning different tags as follows:
for i = 1:length(strings)
uicontrol('Parent', acpg_tab2, 'Style', 'text',...
'String', strings{i},...
'FontSize', 8, 'HorizontalAlignment', 'left',...
'Units', 'normalized',...
'Position', [0.05 (0.995 - 0.05*i) 0.3 0.03],...
'HandleVisibility', 'callback', 'Tag', labeltags{i});
uicontrol('Parent', acpg_tab2, 'Style', 'slider',...
'Min', 0, 'Max', 100, 'Value', 25,...
'Units', 'normalized',...
'Position', [0.375 (1-0.05*i) 0.4 0.03],...
'HandleVisibility', 'callback', 'Tag', slidertags{i},...
'Callback', @sliderChanged);
uicontrol('Parent', acpg_tab2, 'Style', 'edit',...
'Fontsize', 8, 'HorizontalAlignment', 'left',...
'Units', 'normalized',...
'Position', [0.80 (1-0.05*i) 0.15 0.03],...
'HandleVisibility', 'callback', 'Tag', edittags{i},...
'Callback', @editChanged);
end
I'm creating the figure right at the start of the function. I did try adding the initialisation code just at the end of the function but again it always returns an empty list with findobj there.

Sign in to comment.

Accepted Answer

Adam
Adam on 3 Jun 2015
Something like this would work to store the handles. I tend to prefer a more explicit link between a slider and its associated edit box, but given the way they are created, if nothing else changes them you know that the nth slider in the hSliders array corresponds to the nth edit box in the hEditBoxes array.
hSliders = [];
hEditBoxes = [];
for i = 1:length(strings)
uicontrol('Parent', acpg_tab2, 'Style', 'text',...
'String', strings{i},...
'FontSize', 8, 'HorizontalAlignment', 'left',...
'Units', 'normalized',...
'Position', [0.05 (0.995 - 0.05*i) 0.3 0.03],...
'HandleVisibility', 'callback', 'Tag', labeltags{i});
hSliders(i) = uicontrol('Parent', acpg_tab2, 'Style', 'slider',...
'Min', 0, 'Max', 100, 'Value', 25,...
'Units', 'normalized',...
'Position', [0.375 (1-0.05*i) 0.4 0.03],...
'HandleVisibility', 'callback', 'Tag', slidertags{i},...
'Callback', @sliderChanged);
hEditBoxes(i) = uicontrol('Parent', acpg_tab2, 'Style', 'edit',...
'Fontsize', 8, 'HorizontalAlignment', 'left',...
'Units', 'normalized',...
'Position', [0.80 (1-0.05*i) 0.15 0.03],...
'HandleVisibility', 'callback', 'Tag', edittags{i},...
'Callback', @editChanged);
end
If you still prefer to use tags to then do the initialisation then you can do that with this method (though using the indices would be simpler). You just have to do some string manipulation e.g.
sliderTags = get( hSliders, 'Tag' );
sliderControl = hSliders( find( strcmp( sliderTags, requiredTag ) ) );
to get the slider control with 'requiredTag'.
An initialisation method using this should be able to go at the end of your creation function because it does not rely on findobj so it doesn't need the figure to be visualised before you can do your initialisation.
  3 Comments
Christopher Dadswell
Christopher Dadswell on 4 Jun 2015
Just tried it and it works great! Will rewrite the other bits to get rid of my findobj uses. In the end I just added every new slider handle onto the end of hSliders using
hSliders(end+1) = ...
Probably not the best way of doing it because it constantly grows, but couldn't think of a good way of doing it otherwise.
Thanks again for all your help, very much appreciated!
Adam
Adam on 4 Jun 2015
If speed is not an issue you can ignore that. It's not perfect, but sometimes it just isn't worth fussing about trying to presize and get the next empty index if you don't have the information readily available.

Sign in to comment.

More Answers (1)

Ingrid
Ingrid on 2 Jun 2015
Edited: Ingrid on 2 Jun 2015
do you mean you have pasted it in the OpeningFcn?
I have not used the findobj there but I have used it to set background images of pusbuttons so it seems that the uicontrols are already present
worst case scenario you could also just add a menu bar like File-Load and than you can even specify from which mat.file you would like to read in the settings. This option could also be handy if you want to restore to default values after you have made some changes without the need to close and open the app again
  2 Comments
Christopher Dadswell
Christopher Dadswell on 2 Jun 2015
Hi Ingrid, thanks for the response.
I'm not using GUIDE so there was no OpeningFcn by default. Instead, when I create the figure that forms the basis of the GUI I specified the 'CreateFcn' property as a function I created myself.
I was already planning to have a 'load' button so that I can choose different configurations (and a save one to store versions that have been modified), but ideally I'd like a certain configuration to just pop up when you start GUI or a bunch of other things (plots based on the parameters) won't pop in either.
Ingrid
Ingrid on 2 Jun 2015
I was indeed assuming that you were using GUIDE because when you are creating the GUI programatically there is no need to use the findobj but it is better to store the handles of the uicontrols directly as also suggested by Adam

Sign in to comment.

Categories

Find more on Interactive Control and Callbacks in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!