User Interface problem in callback function

1 view (last 30 days)
I am creating a structure , with two popupmenus and two buttons. My task is to click either of the button. Click on First button should disable the second button and enable the two popupmenus. Click on the second button should disable the first button and disable the two popupmenus.
when I was passing the aruguments the whole structure is not being passed. and hence when I click the first button its shows an error
Reference to non-existent field 'pb2'.
Error in fntest_final>trainclassifier (line 24)
set(MW.pb2,'Enable','off');
Error while evaluating UIControl Callback
Directly clicking on the second button shows no error, and but in structure i can see only two popupmenus and one pushbutton(pb1). is there any way that i can send the whole structure??
function fntest_final()
close all;
%%creates Main Window Panel
MW.f = figure('Name','Project','Numbertitle','Off','Menubar','None','Units','Pixels','Position', [100 10 700 1000],'Resize','Off');
movegui(MW.f,'center')% adjust to the center point.
col = get(MW.f,'color');% taking the color of the back ground.
MW.pop1 = uicontrol('Style','Popupmenu','Position',[300 950 100 20],'Foregroundcolor', [0 0 0],'Backgroundcolor', [1 1 1],'Tag','popuplist',...
'String',{'Fire Sample';'Smoke Sample';'Plugin'},'Enable','off',...
'Callback',@popuppush);
%MW.pop2 = uicontrol('Style','Popupmenu','Position',[500 950 100 20], 'Foregroundcolor', [0 0 0],'Backgroundcolor', [1 1 1],'Tag','popuplist',...
'String',{'Classifier 1';'Classifier 2 ';'Plugin'},'Enable','off',...
'Callback',@popuppush);
% Creating clearlist Button for all list boxes.
MW.pb1 = uicontrol('Style','Pushbutton','String','Train','Position',[50 900 200 80],'FontWeight','Bold','ForegroundColor',[0.584 0.082 0.122],'Backgroundcolor',[0.941176 0.941176 0.941176],'Enable','on', 'Callback',{@trainclassifier,MW});
MW.pb2 = uicontrol('Style','Pushbutton','String','Test','Position',[50 800 200 80],'FontWeight','Bold','ForegroundColor',[0.584 0.082 0.122],'Backgroundcolor',[0.941176 0.941176 0.941176],'Enable','on', 'Callback',{@testclassifier,MW});
end
function []= trainclassifier(varargin)
MW = varargin{3};
set(MW.pop1,'Enable','on');
set(MW.pb2,'Enable','off');
end
function [] = testclassifier(varargin)
MW = varargin{3};
%set(MW.pb1,'Enable','on');
set(MW.pop1,'Enable','off');
end

Accepted Answer

Walter Roberson
Walter Roberson on 23 Jan 2016
MW.pb1 = uicontrol('Style','Pushbutton','String','Train','Position',[50 900 200 80],'FontWeight','Bold','ForegroundColor',[0.584 0.082 0.122],'Backgroundcolor',[0.941176 0.941176 0.941176],'Enable','on' );
MW.pb2 = uicontrol('Style','Pushbutton','String','Test','Position',[50 800 200 80],'FontWeight','Bold','ForegroundColor',[0.584 0.082 0.122],'Backgroundcolor',[0.941176 0.941176 0.941176],'Enable','on' );
set(MW.pb1, 'Callback', {@trainclassifier,MW});
set(MW.pb2, 'Callback', {@testclassifier,MW});
The difficulty that you are having is that when you pass a variable in a callback like that, it is always the value of the variable as of the time you create the callback that is captured for use. It is not the name of the variable that is used. So at the time you were using MW in creating MW.pb1, there was no pb1 or pb2 field in MW, and it is that version of MW that would be used each time the callback was invoked. Then after the callback was created, the handle of the uicontrol was assigned to MW.pb1, so at the time the second callback was created, MW would have a pb1 field but not a pb2 field, so it would be that different MW that would be passed for the second callback. It would not be until after the callback had been created that the uicontrol handle would have been assigned to MW.pb2 completing the value of MW.
The changed version creates the two controls and assigns the appropriate fields before creating the callback. Then the MW value that is captured when the callback is created is the version that has both MW.
Notice that if you later changed a field in MW then the callbacks would not receive the updated values.
The structure {@trainclassifier,MW} is creating a cell array by value, a cell array with a function handle and some contents that are a structure. It is not creating some code for future execution that would get the then-current value of MW.
If you have ever looked at GUIDE, it is this reason that GUIDE often creates callbacks as strings -- because it needs to get the current value of the handles structure for each callback, and that requires executing code to fetch the current value.

More Answers (0)

Categories

Find more on Migrate GUIDE Apps 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!