Reputation: 5960
Is there a general purpose way to determine when a Matlab GUI callback function begins and then has returned to the dispatcher?
I want to lock out user interaction while callbacks are running to completion and also show busy status while callbacks are running. Is there a dispatcher accessible where I can insert this code, or do I have to put it into every callback function.
I am aware of the modal waitbar but I want to avoid using that as much as possible. (They can't be killed gracefully.)
Upvotes: 0
Views: 182
Reputation: 32084
I suggest to add a wrapper function, that wraps all original UIControl callback functions.
The wrapper function does the following:
You can also start a timer before original callback, and stop the timer when callback returns (the timer can simulate a wait bar using an image built int to the main GUI [image inside a small axes]).
Example (assuming GUI was created using guide
tool):
% --- Executes just before untitled1 is made visible.
function untitled1_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to untitled1 (see VARARGIN)
% Choose default command line output for untitled1
handles.output = hObject;
%Add wrapper function to each UIControl callback.
A = findall(hObject.Parent, 'Type', 'UIControl');
for i = 1:length(A)
set(A(i), 'Callback', {@wrapper, A(i).Callback});
end
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes untitled1 wait for user response (see UIRESUME)
% uiwait(handles.figure1);
function wrapper(ObjH, EventData, origCallback)
disp('Do somthing before callback begins...');
%You can also start a timer.
%Disable all UIControl objects, before executing original callback
A = findall(ObjH.Parent, 'Type', 'UIControl');
for i = 1:length(A)
set(A(i), 'Enable', 'off');
end
%Execute original callback.
feval(origCallback, ObjH, EventData);
disp('Do somthing after callback ends...');
%You can also stop the timer.
%Enable all UIControl objects, after executing original callback
for i = 1:length(A)
set(A(i), 'Enable', 'on');
end
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
pause(1);
set(handles.pushbutton1, 'BackgroundColor', [rand(1,1), rand(1,1), rand(1,1)]);
Upvotes: 1
Reputation: 22215
You can generally lock user interaction with the waitfor
command. It is designed to do exactly what you ask.
You can make your callback function update a handle property when it's finished, which can cause waitfor
to exit. If that handle property you're updating also happens to hold the result of a tic / toc
operation timing the duration of your callback function, then you kill two birds with one stone :)
Upvotes: 0