How to create callback function from matlab code

Hi everybody!
Some times ago I wrote about "how to create pushbutton using matlab code"... I solved this problem (thanks to all advice you gave me), but now, I have to create the callback function...
I post the code I wrote...
global UNI;
global c;
global bh;
UNI=unique(institute);
for i=1:length(UNI)
b=['Institute_' char(UNI(i))];
c=['PB_Ist_' char(UNI(i))];
end
N_PB = length(UNI); %number of pushbutt
bh = zeros(N_PB,1);
%pushbuttons dimension
wdt=104;
hgt=22;
for k=1:N_PB
a=['Istituto ' char(UNI(k))];
z=['PB_', b];
bh(k) = uicontrol(gcf, 'Style', 'pushbutton', 'Tag', ...
z, 'Units', 'pixel', 'Position', ...
[(50+(wdt*1.5*(k-1))) 500 wdt hgt], 'String', a);
set(bh(k), 'Callback', z)
end
When I set visibility, I use
for s=1:length(UNI)
c=['PB_Ist_' char(UNI(s))];
handles.(c)=bh(s);
set(handles.(c), 'visible', 'off');
end
Now... I have to click on a pushbutton and generate other buttons... To generate them I need the function!
Something like
function PB_Example_Callback(hObject, eventdata, handles)
but I DON'T KNOW HOW... I tried to write manually my function, but it doesn't work... Any ideas??

 Accepted Answer

Hi, Jethro
Please try my code below.
This code create 4 buttons when you press the main button.
I hope you can modify it yourself for your purpose.
If this example is not clear, please tell me later.
function GUI1(action);
global G;
if nargin == 0, action = 'init'; end
switch action
case 'init'
G.Hfig = figure('unit','pixel','position',[100 100 400 400]);
G.HButton = uicontrol(G.Hfig,'unit','pixel',...
'style','pushbutton',...
'string','Hospital1',...
'position',[25 350 75 25],...
'callback','GUI1 create');
case 'create'
str = {'Departement1','Departement2','Departement3','Departement4'};
for i = 1 : length(str);
G.DButton(i) = uicontrol(G.Hfig,'unit','pixel',...
'style','pushbutton',...
'string',str{i},...
'position',[50 350-(i*30) 75 25],...
'tag',num2str(i),...
'callback','GUI1 departement');
end
case 'departement'
switch str2num(get(gcbo,'tag')),
case 1, disp('1');
case 2, disp('2');
case 3, disp('3');
case 4, disp('4');
end
end

13 Comments

Can you say me what's G??
G is global variable.
It is usefull to make all objects (buttons, figure, etc) as global objects so you can access them anywhere in this function.
I'm trying to edit your function... I'll let you know... Thanks a lot!!
Uhm... I tried to call your function passing "action" like attribute, and to copy the whole code...
In the first case, using
[mycode......]
GUI1(action);
[set blah blah blah]
Matlab says to me: ??? Undefined function or variable 'action'.
If I use the whole code it creates me another function (starting from "function GUI1(action)" and it doesn't work... Because I have to insert in a .m file already assigned to a fig (infact I edited G.Hfig with gcf)...
GUI1('init')
GUI1('create')
and so on.
Chandra,I edited my code, and I only have a question! If I wanted to set pushbutton as not visible, how can I recover callbacks from your function??
Please explain what you mean by "recover callbacks" ? But unless you mean "How does the chosen callback get activated when the user clicks the button", the mechanism will not depend on whether the button is visible or not.
Earlier I wrote,
It is not clear what you mean by "recall" the callback. You can get() the 'Callback' property of the handle. This does have uses, but it is not the most common thing to do. I have been coming to find that if I am get()'ing the Callback of a routine for any reason other than to simulate that control having been invoked by the user, then I am probably creating something that is difficult to maintain and should be handled some other way.
My quest is: if I want to set visibility as off, normally I write
set(handles.TAG, 'visible', 'off');
According to the code of Chandra, I want to set the pushbutton created in the 'init' case as not visible after clicking on it, but I don't understand what I have to write, how to write my set!
set(hObject, 'visible', 'off')
It doesn't work... If you look at the code below, I have to insert this set "after clicking" on a pushbutton (in 'create' case). When I click on a "bh" pushbutton, ALL "bh" pushbuttons have to desappear, while "dih" pushbuttons have to appear...
For this I was wondering what were callbacks I have to use...
In the previous code I wrote when I posted my quest, you can see there's an assignment:
for s=1:length(UNI)
c=['PB_Ist_' char(UNI(s))];
handles.(c)=bh(s);
set(handles.(c), 'visible', 'off');
end
This set you see works correctly...
set(bh,'Visible','off'); set(dih,'Visible','on');
You are permitted to pass arrays of handles to set()
Thanks Walter, I solved this problem! Any ideas about why it creates me only the first pushbutton in 'create' case?

Sign in to comment.

More Answers (5)

set ( handles.button, 'Callback', {@FunctionHandle inputArguments} );
edit example:
function test
d = dialog ( 'windowstyle', 'normal' );
uicontrol ( 'parent', d, 'style', 'pushbutton', 'string', 'push me', 'Callback', {@PB_Callback rand(10,1)}, 'position', [100 100 100 100] );
end
function PB_Callback ( obj, event, randomInput )
disp ( 'PB Called - extra arg' );
randomInput
end
you should probably have a look at this FEX

5 Comments

I must change the code {@FunctionHandle inputArguments} adding some parameters??
I tried using it as you written but it doesn't work... I also tried replacing "inputArguments" with my "z", but it's the same... Can you explain me how to set it?? Thanks a lot!
Hi, can you tell me your detailed problem?
You said 'I have to click on a pushbutton and generate other buttons'
What does it means?
added an example above on how to create a pushbutton wiht a callback and a single extra input argument.
Also added a link to a good FEX with lots of GUI examples which you should look at to help you learn.
Robert, you created d to set the pb in the dialog box, right??
So, if I want to create my pb in the figure can I use 'gcf'?
And, I know that I'm smashing your bal*s, but can you give me an example about my code??
I can't edit it, it always give me lots of errors... I'm going to throw my computer off the balcony!
whats your variable institute?
You should just be able to add:
set(handles.(c), 'callback', {@PB_Callback c});
to the line below where you make your PB invisible...
And yes I craeted a new dialog which I put a button (pb) on. You can use gcf yes - but that might put it on a figure you dont want it on - by stipulating a new dialog you force it to where you want.

Sign in to comment.

This is bad program design, and I already explained why over in http://www.mathworks.com/matlabcentral/answers/25221-how-can-i-know-and-set-callbacks-i-created-by-functions and I already showed an alternative design that is easy to work with.
You have encountered one of the problems I set out in that previous discussion, and you are not going to be able to solve the problem as long as you are generating function names for your callbacks.

2 Comments

...Can you make me an example based on my code with your solution?? I read again your answ but there's something I can't understand... :(
After having set the callback via
set(bh(k), 'Callback', {@PB_Inst, UNI(k)} )
then you have a single callback routine
function PB_Inst(src, evt, thisUNI)
fprintf('PB_Inst callback requested for "%s"\n", thisUNI);
end
You have not indicated what you want to _do_ in the callbacks, which makes it difficult to suggest code that might be appropriately dependent on thisUNI

Sign in to comment.

This is my edited code:
function GUI1(action)
global UNI;
global ist_num;
global REP;
global REPU;
global prog_reparto;
global istituto;
ist_num=str2double(istituto);
for i=1:length(UNI)
indiceist=find(strcmp(istituto, UNI(i)));
REP=prog_reparto(indiceist);
REPU=unique(REP);
end
lung=104;
alt=22;
if nargin == 0, action = 'init'; end
switch action
case 'init'
bh=zeros(size(UNI));
for i=1:length(UNI)
a=['Istituto ' char(UNI(i))];
bh(i) = uicontrol(gcf,'unit','pixel',...
'style','pushbutton',...
'String', a,...
'position',[(50+(lung*1.5*(i-1))) 500 lung alt],...
'callback','GUI1 create');
end
case 'create'
dih=zeros(size(REPU));
for j=1:length(REPU)
b=['Reparto ' char(REPU(j))];
dih(j) = uicontrol(gcf,'unit','pixel',...
'style','pushbutton',...
'String',b,...
'position',[(50+(lung*1.5*(j-1))) 500 lung alt],...
'tag',num2str(j),...
'callback','GUI1 departement');
end
case 'departement'
switch str2num(get(gcbo,'tag')),
case 1, disp('1');
case 2, disp('2');
case 3, disp('3');
case 4, disp('4');
end
end
The first part takes global variables and the next for loop find departments for each institute.
After that, the code Chandra wrote starts with my edits: the first case, 'init', creates a number of pushbuttons according to "UNI" (it represents the unique of my institutes).
In the 'create' case, I used the same method to create a number of pushbuttons equal to REPU (unique of departments). It works, but now I noted that in 'department' case, I only have 4 cases... I need that this cases are dynamic, but if I add a for loop, Matlab report "case" before "department" as an error...
I also wanted to know how to use set() and get() in these specific cases because I'm not sure about what I have to write as handles... :) Any ideas?? ;)
Edit 1
I have another problem... When I click on a pushbutton, it has to create different pushbuttons... But it creates only a pb, even if I set the for loop about more objects... What do you think about this? How can I fix?

5 Comments

In the "for i" loop you have just before lung=104, you overwrite REP and REPU each time through the loop. REPU will be left at whatever is appropriate for the last entry.
Note: whatever you think you are doing in that loop should probably be done in the 'init' case, since you have set those variables up as global variables (that thus will retain values between calls.)
I moved the for loop as you adviced (I moved REP and REPU out of the loop too), but I have the same situation, only the first one pb...
What is the current code for setting REP and REPU is? Have you tested to be sure that REPU is not of length 1 when you create it, and have you tested to be sure that REPU is not of length 1 when you use it for the 'create' loop ?
I'll check it tomorrow morning... I'll let you know...
Thanks for your help!
Hi,
what these buttons do when you hit them?
Do they perform similar actions?
If so,
case 'departement'
l = length(G.str);
for x = 1 : l
if str2num(get(gcbo,'tag')) == x
disp(x);
end
end
You can change 'l' with the number of your pushbuttons in 'create'

Sign in to comment.

Hi everybody, guys! I solved my problem with cases, but I still have problems with creation of buttons.. As Walter adviced me, I tested my code, and I have a bad result:
I have an array totally fulled with "1", and the unique give me ans="1"
I explain you what I have to do...
I'm creating an analysis software (for a university project): it has to make some statistics about a group of data coming from some hospitals...
I have to analyse 3 hospitals (called 'institute'): for each one of them, I have different departments... Unfortunately, they have the same identificator, something like
Institute 1 -> Deps 1,2,3,4,5 Institute 2 -> Deps 1,2,3 Institute 3 -> Deps 1,2,3,4
In this code
for i=1:length(UNI)
index_inst=find(strcmp(institute, UNI(i)));
DEP=dep_number(index_inst);
DEPu=unique(DEP);
end
I wanted to find departments for any institute... But the result is my "1"-array...
My source files is formed by 31 coloumns: the 3th and the 5th contains rispectivly institutes and departments...
Can you help me to solve this problem?? I can't go on with the job! :(

4 Comments

Suppose you know that you will have at most 99 institutes per department. Then you can calculate an indicator variable as "department code times 100 plus institute code"
And make sure that you do not overwrite DEP and DEPu in the loop.
I'm sorry, I don't understand what you are trying to explain me... I tried lots of codes, even using cell arrays, I don't know what to do!
nUNI = length(UNI);
DEP = cell(nUNI,1);
for i = 1 : nUNI
index_inst = find(strcmp(institute, UNI(i)));
DEP{i} = index_inst * 100 + dep_number(index_inst);
end
DEPu = unique([DEP{:}]);
No overwrites in the loop, per-institute DEP is kept instead of discarded, DEP numbers build in the institute number as part of them so DEP numbers do not class between institutes, unique is done over all department numbers.
You can recover the institute number from a DEPu by dividing by 100 and taking the integer part.
Thanks Walter... But I haven't got my dep_number... I have to find it starting by my institute...
When I click on an Istitute I have to generate a number that I don't know at the beginning... I'll know it when I'll see the pushbuttons...

Sign in to comment.

I post you the code I wrote using cell arrays:
function GUI1(action)
global UNI;
global ist_num;
global REP;
global REPU;
global prog_reparto;
global istituto;
global b;
global bh;
global dih;
global R;
global t;
global f;
UNI=unique(istituto)
ist_num=str2double(istituto);
lung=104;
alt=22;
if nargin == 0, action = 'init'; end
switch action
case 'init'
bh=zeros(size(UNI));
R=cell(size(UNI))';
for i=1:length(UNI)
a=['Istituto ' char(UNI(i))];
indiceist=find(strcmp(UNI(i), istituto));
REP=prog_reparto(indiceist);
REPU=unique(REP);
R{i}=REPU
t=i;
bh(i) = uicontrol(gcf,'unit','pixel',...
'style','pushbutton',...
'String', a,...
'position',[(50+(lung*1.5*(i-1))) 500 lung alt],...
'callback','GUI1 create');
end
case 'create'
set(bh, 'visible', 'off');
t=f;
fprintf(1, '%d\n', f);
for i=1:length(UNI)
f=bh(i);
REPU=R{i}'
dih=zeros(size(REPU));
for j=1:length(REPU)
b=['Reparto ' char(REPU(j))];
dih(j) = uicontrol(gcf,'unit','pixel',...
'style','pushbutton',...
'String',b,...
'position',[(50+(lung*1.5*(j-1))) 500 lung alt],...
'tag',num2str(j),...
'callback','GUI1 departement');
end
end
case 'departement'
for k=1:length(REPU)
if str2num(get(gcbo, 'tag'))==k
disp (k)
end
end
end
I created a cell array to insert deps for each institute. I created two variables (t and f), because I wanted to try to have a single value to pass at the 'create' case when I click on a specific pushbutton (Ex: If i represents the first pushbutton, t will be equal to 1. If I should click on the pushbutton of the first institute, my t value must pass at the other case to "tell it" I have clicked on that specific pushbutton and I need a specific number of deps).
When I run my code (considering a file with 3 institutes which have respectivly 4, 5 and 1 deps)
R= {4x1 cell} [] []
R= {4x1 cell} {5x1 cell} []
R= {4x1 cell} {5x1 cell} {1x1 cell}
f= 1 2 3
1
2
3
REPU= '1' '2' '3' '4'
REPU= '1' '2' '3' '4' '5'
REPU= '1'
But I CAN'T UNDERSTAND WHY IF I CLICK ON THE FIRST PUSHBUTTON (THAT SHOULD GIVE TO ME FOUR DEPS) I HAVE FIVE PUSHBUTTONS! I thought "It overwrites something..." But WHY IT STOPS AT THE SECOND CELL AND NOT THE LAST ONE??????

3 Comments

If I "crash" my code at the first pb, it works correctly...
According to you what's the problem??

Sign in to comment.

Categories

Find more on MATLAB 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!