|
[top posting repaired]
In article <ftajte$hpa$1@fred.mathworks.com>,
"Yuri Geshelin" <geshelin@hotmail.com> wrote:
> Doug Schwarz <see@sig.for.address.edu> wrote in message
> <see-5B0A29.12240405042008@71-129-133-66.dollamir.com>...
> > In article <ft800d$jcr$1@fred.mathworks.com>,
> > "Yuri Geshelin" <geshelin@hotmail.com> wrote:
> >
> > > Ok, I now have a fully working example, which I tried
> to
> > > make as short as possible. Below are 5 functions:
> > > global_example, refresh_all, plot_all, random_pick,
> > > time_pick. Execute global_example.m, and shouldn't be
> hard
> > > to figure out what the application does.
> > >
> > > %%%%%%%%%%%%%%% top of global_example
> > > function global_example
> > > figure(1),clf
> > > set(1,'position',[100 500 300 300])
> > > u1 = uicontrol('position',[ 20 20 100
> 30],'string','Random
> > > pick','callback','random_pick');
> > > u2 = uicontrol('position',[ 20 60 100
> 30],'string','Month
> > > pick','callback','time_pick(2)');
> > > u3 = uicontrol('position',[ 20 100 100
> 30],'string','Date
> > > pick','callback','time_pick(3)');
> > > u4 = uicontrol('position',[ 20 140 100
> 30],'string','Plot
> > > all','callback','plot_all');
> > > u5 = uicontrol('position',[180 140 100
> > > 30],'string','Refresh all','callback','refresh_all');
> > > plot_all
> > > %%%%%%%%%%%%%% bottom of global_example
> > >
> > > %%%%%%%%%%%%%%% top of refresh_all
> > > function refresh_all
> > > global final_handles index_handles
> > >
> > > if ishandle(final_handles)
> > > set(final_handles(index_handles),'color','r')
> > > end
> > > %%%%%%%%%%%%%%%%% bottom of refresh_all
> > >
> > > %%%%%%%%%%%%%%% top of plot_all
> > > function plot_all
> > > global final_handles index_handles
> > >
> > > index_handles = [];
> > > figure(2), clf
> > > set(2,'position',[600 500 300 300])
> > > final_handles = plot(repmat(1:31,2,1),'color','b');
> > > %%%%%%%%%%%%%%%%% bottom of plot_all
> > >
> > > %%%%%%%%%%%%%%% top of random_pick
> > > function random_pick
> > > global index_handles
> > > index_handles = [index_handles round(rand(1,5)*30)+1];
> > > %%%%%%%%%%%%%%%%% bottom of random_pick
> > >
> > > %%%%%%%%%%%%%%% top of time_pick
> > > function time_pick(n)
> > > global index_handles
> > > c = clock;
> > > index_handles = [index_handles c(n)];
> > > %%%%%%%%%%%%%%%%% bottom of time_pick
> > >
> > > Thanks Doug and everyone who will show me how to make
> do
> > > without GLOBAL.
> > >
> > > Yuri
> >
> >
> > Hi Yuri,
> >
> > Well, I had to correct a few problems with your example,
> but otherwise
> > it's a good one. I think I have correctly figured out
> what it is
> > supposed to do.
> >
> > I have two ways of doing the same thing without any
> global variables.
> > The first uses nested functions. With nested functions
> we have cheated
> > a bit because a nested function can access variables in
> the calling
> > program and this is very much like global variables in
> that you have to
> > be careful when debugging because all variables do not
> get passed
> > explicitly into the nested function workspace.
> Nevertheless, it is a
> > good technique (IMO) because you don't have to worry
> about name
> > conflicts with variables in other programs.
> >
> > The second example uses the method where, instead of
> globals, we pass
> > data around in a structure which gets stored in the
> UserData of the main
> > figure. It's a little more cumbersome because inside
> each subfunction
> > you have retrieve the UserData and then put it back at
> the end, but
> > because this is an explicit operation you might like it
> better than the
> > nested function approach.
> >
> > If you have a really old version of MATLAB and don't have
> function
> > handles (the @ operator) then we can modify the second
> example to use
> > the switchyard technique. Let me know if you need that.
> >
> > Anyway, here are the programs:
> >
> > %-------------- nested_fcn_example.m ---------------------
> ---
> > function nested_fcn_example
> > fig = figure('position',[100 500 300 300]);
> > u1 = uicontrol('position',[ 20 20 100 30],...
> > 'string','Random pick',...
> > 'callback',@random_pick);
> > u2 = uicontrol('position',[ 20 60 100 30],...
> > 'string','Month pick',...
> > 'callback',{@time_pick,2});
> > u3 = uicontrol('position',[ 20 100 100 30],...
> > 'string','Date pick',...
> > 'callback',{@time_pick,3});
> > u4 = uicontrol('position',[ 20 140 100 30],...
> > 'string','Plot all',...
> > 'callback',@plot_all);
> > u5 = uicontrol('position',[180 140 100 30],...
> > 'string','Refresh all',...
> > 'callback',@refresh_all);
> >
> > final_handles = [];
> > index_handles = [];
> > fig2 = [];
> > axes2 = [];
> >
> > plot_all
> >
> > function refresh_all(varargin)
> > if ~isempty(final_handles)
> > set(final_handles(index_handles),'color','r')
> > end
> > end
> >
> > function plot_all(varargin)
> > index_handles = [];
> > if isempty(fig2)
> > fig2 = figure('position',[600 500 300 300]);
> > axes2 = gca;
> > end
> > final_handles = plot(axes2,repmat
> (1:31,2,1),'color','b');
> > end
> >
> > function random_pick(varargin)
> > index_handles = round(rand(1,5)*30)+1;
> > end
> >
> > function time_pick(varargin)
> > n = varargin{end};
> > c = clock;
> > index_handles = c(n);
> > end
> >
> > end
> > %------------ end nested_fcn_example.m -------------------
> ---
> >
> >
> >
> > %--------------- userdata_example.m ----------------------
> ---
> > function userdata_example
> > fig = figure('position',[100 500 300 300]);
> > u1 = uicontrol('position',[ 20 20 100 30],...
> > 'string','Random pick',...
> > 'callback',@random_pick);
> > u2 = uicontrol('position',[ 20 60 100 30],...
> > 'string','Month pick',...
> > 'callback',{@time_pick,2});
> > u3 = uicontrol('position',[ 20 100 100 30],...
> > 'string','Date pick',...
> > 'callback',{@time_pick,3});
> > u4 = uicontrol('position',[ 20 140 100 30],...
> > 'string','Plot all',...
> > 'callback',@plot_all);
> > u5 = uicontrol('position',[180 140 100 30],...
> > 'string','Refresh all',...
> > 'callback',@refresh_all);
> >
> > info.final_handles = [];
> > info.index_handles = [];
> > info.fig2 = [];
> > info.axes2 = [];
> >
> > set(fig,'UserData',info)
> >
> > plot_all(u4)
> >
> >
> > function refresh_all(varargin)
> > fig = gcbf;
> > info = get(fig,'UserData');
> > if ~isempty(info.final_handles)
> > set(info.final_handles
> (info.index_handles),'color','r')
> > end
> >
> >
> > function plot_all(varargin)
> > fig = get(varargin{1},'Parent');
> > info = get(fig,'UserData');
> > info.index_handles = [];
> > if isempty(info.fig2)
> > info.fig2 = figure('position',[600 500 300 300]);
> > info.axes2 = gca;
> > end
> > info.final_handles = plot(info.axes2,repmat
> (1:31,2,1),'color','b');
> > set(fig,'UserData',info)
> >
> >
> > function random_pick(varargin)
> > fig = gcbf;
> > info = get(fig,'UserData');
> > info.index_handles = round(rand(1,5)*30)+1;
> > set(fig,'UserData',info)
> >
> >
> > function time_pick(varargin)
> > fig = gcbf;
> > info = get(fig,'UserData');
> > n = varargin{end};
> > c = clock;
> > info.index_handles = c(n);
> > set(fig,'UserData',info)
> > %------------- end userdata_example.m --------------------
> ---
> >
> > --
> > Doug Schwarz
> > dmschwarz&ieee,org
> > Make obvious changes to get real email address.
> Many thanks Doug,
>
> for teaching me a good programming style. I went over your
> examples, both are working nicely and make sense. I just
> want to share some thoughts.
>
> 1) I like the nested approach better, because it is a bit
> faster. Not that this is very important though. (And in
> this case, it is not important at all).
>
> 2) Instead of using figure's userdata, you can use that of
> the root (see sfreeman's post of 28 Mar). But this is a
> potential source of errors, because you can dump too many
> variables into this storage, while in the case of the
> figure at hand, you will focus on that figure.
One of the advantages of using the UserData of the gui figure is that
you can open multiple copies of your application and when you make that
figure go away you delete all the data associated with that version. If
you store the data in the UserData of the root then you're either
limited to one instance of your application at a time or else you have
to manage multiple sets of data.
> 3) I understand, there is a third way of doing it - to make
> a function recursively call itself, right? Something as you
> posted here on 31 March.
Yes, that's the old method that was necessary before function handles.
> 4) Maybe there are yet more ways of doing it, e.g. to use a
> constructor method, or to call a function, in which the
> structure is declared as a persistent. I will explore it
> when I will get a chance.
Again, you will have to manage multiple sets of data if you want to be
able to have more than one instance of your application open so I don't
recommend it.
--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.
|