Using a Matlab GUI Button to Halt a running callback
21 views (last 30 days)
Show older comments
I have a Matlab GUI with a button initially called 'Run'. When I hit that button a loop is started that does some processing, and I change the name of the button to 'Halt'. When the 'Halt' button is pressed, I want the GUI to recognize the button press, and halt the callback that is running. So my question is, is there any property of a Button that I can use that will be changed when my user hits my button the 2nd time? (If I can detect the button has been pressed, then I can halt the running loop).
0 Comments
Accepted Answer
Joseph Cheng
on 4 Sep 2014
This can be done but for ease i would change to a toggle button. Save the below code as a whole under opti.m and then run it. without spending too much time i was trying to do it with a push button and update flags but haven't had to time to think through the handle update flow. however since the toggle button is handled at the handle level (MATLAB employees please correct me on that) and not running another function to update a value it will update while in the loop.
function opti();
fig = figure;
ax = axes;
axis([0 100 -5 5]);
b = uicontrol('Style', 'togglebutton', 'String', 'RUN',...
'Position', [20 20 50 20],...
'Callback', {@buttonpress,ax});
end
function buttonpress(hObject,event,ax)
switch get(hObject,'Value')
case 0
set(hObject,'String','HALT')
case 1
set(hObject,'String','RUN')
cla(ax);
end
axes(ax)
hold on;
t=0;
while get(hObject,'Value') || t>30;
t=t+1;
y=sin(2*pi*t/10);
plot(t,y,'.');
pause(.1);
end
end
0 Comments
More Answers (2)
Geoff Hayes
on 4 Sep 2014
Michael - I don't think that you can have a button interrupt its own callback through a call to the callback, which is kind of what you want to do (or at least that is my interpretation of your question). I tried playing around with the push button and the toggle button widgets, and while I could get the callback to fire a second time, it had no real impact on the first callback which is still going because of the while or for loop. If you were using a timer instead (to do the periodic work) then you could do something on the second call to stop the timer.
For your question, is there any property of a Button that I can use that will be changed when my user hits my button the 2nd time, you do kind of know that it is the second time that the button has been pushed because of the button string value - either it is Start (first button press) or Halt (second button press). So you could do something in the callback that checks the "state" of the string value and if the first button press, then start the loop; and if the second button press, then somehow flag the first callback call to stop. It can be done (and I just mocked up something for it) but I would counsel against this sort of coding. It seems clumsy and probably prone to errors.
I would suggest that you just add a second button called Halt that, when pressed, would interrupt the Start button callback and set some sort of flag that the first callback would recognize and force itself to break out of the loop. We can interrupt the first callback if in its loop there is call to one of drawnow, figure, getframe, pause, or waitfor (see interrupt callback execution for details).
Suppose you have two push buttons called start and halt. Then the callback for the start button could be something like
function start_Callback(hObject, eventdata, handles)
% disable the start button
set(hObject,'Enable','off');
% enable the halt button
set(handles.halt,'Enable','on');
% flag that the loop is running
handles.doLoop = true;
guidata(hObject,handles);
% start loop
fprintf('starting while loop\n');
while true
% do stuff
pause(0.001);
% should we continue?
handles = guidata(hObject);
if ~handles.doLoop
break;
end
end
fprintf('exiting while loop\n');
% enable the start button
set(hObject,'Enable','on');
% disable the halt button
set(handles.halt,'Enable','off');
All it does is enables and disables buttons as it sees fit, creates a flag that is set to true to indicate that the loop should be executed ( doLoop ), and does the loop. At each pass through the loop, it grabs the latest handles data and checks the doLoop flag. Once it is set to false, then we exit the loop and we're done. Note that I've included the pause command so that this callback can be interrupted.
The halt callback is much simpler: it just sets the doLoop flag to false.
function halt_Callback(hObject, eventdata, handles)
% flag that the loop should be stopped
handles.doLoop = false;
guidata(hObject,handles);
Try the above. Note that you may still need to add some extra logic to handle the case where the user tries to close the GUI (via the x button). The loop will still be running, and so should be interrupted in a manner similar to the user pressing the Halt button.
0 Comments
See Also
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!