问题
It's been some time since using Matlab and I've never used it for any GUI creation until now. My goal is to have a button which I can press, and then have the results plotted as they are calculated. The button should toggle between 'Start' and 'Stop' depending on what is happening. These results are collected for several iterations and each iteration gives another data point.
My solution was to pass the axes to the function doing the calculations, which can then plot to the axes. This works, however while this is happening the button won't toggle to 'Stop' until after the plotting is complete. Can I make the function non-blocking? Am I even going about this is in the best method possible? How will I be able to stop the calculations with the 'Stop' button? Will I just need to create a thread for this (does matlab support threading)?
I have been testing my ideas with a simple function to draw a sine
function [ t,y ] = slowSin(ax)
%Plot a sin curve slowly
t = [0:0.06:4*pi];
y = sin(1.5*t);
for i = 1:length(t)
plot(ax, t(1:i), y(1:i))
pause(0.1)
end
I haven't thought of threading until now. I will look into that shortly, but all help is appreciated.
回答1:
First of all, MATLAB does not do multithreading for any graphics so you have to get creative.
Also, you'll want to use drawnow to flush the callback and rendering events if you're trying to do some plotting in the middle of your computations.
As far as knowing when to stop, you can maybe pass the graphics handle of the button to your computations, and it can check the value each iteration?
I have an example that uses a persistent variable to keep track of the current iteration and allows the user to "pause" the calculation by unclicking the toggle button.
function guiThing()
figure();
hbutton = uicontrol('style', 'toggle', 'String', 'Start');
hplot = plot(NaN, NaN);
nIterations = 1000;
set(gca, 'xlim', [1 nIterations], 'ylim', [1 nIterations])
set(hbutton, 'callback', @(s,e)buttonCallback())
function buttonCallback()
% If the button is depressed, calculate the thing
if get(hbutton, 'value')
calculateThing(hbutton, hplot, nIterations);
end
end
end
% This function can live anywhere on the path!
function calculateThing(hbutton, hplot, nIterations)
% Keep track of data with persistent variables
persistent iteration
% First time to call this function, start at 1
if isempty(iteration); iteration = 1; end
for k = iteration:nIterations
iteration = k;
% If the button is not depressed then stop this
if ~get(hbutton, 'value')
return
end
% Update plotting in some way
curdata = get(hplot);
set(hplot, 'XData', [curdata.XData k], ...
'YData', [curdata.YData, k])
% Flush drawing queue
drawnow
fprintf('Iteration: %d\n', iteration);
end
end
You can use the persistent variables to keep track of any other data that needs to persist between iterations (and stops and starts).
来源:https://stackoverflow.com/questions/35803853/how-to-make-a-function-non-blocking-dynamic-plotting-in-matlab-gui