Как сделать функцию неблокирующей? Динамический график в графическом интерфейсе Matlab

Прошло некоторое время с тех пор, как я использовал Matlab, и до сих пор я никогда не использовал его для создания графического интерфейса. Моя цель - иметь кнопку, которую я могу нажать, а затем отображать результаты по мере их расчета. Кнопка должна переключаться между «Старт» и «Стоп» в зависимости от того, что происходит. Эти результаты собираются для нескольких итераций, и каждая итерация дает другую точку данных.

Мое решение состояло в том, чтобы передать оси функции, выполняющей вычисления, которая затем может отображать оси. Это работает, однако, пока это происходит, кнопка не переключается на «Стоп» до тех пор, пока не будет завершено построение графика. Можно ли сделать функцию неблокирующей? Я даже собираюсь об этом в наилучшем возможном методе? Как я смогу остановить вычисления с помощью кнопки «Стоп»? Мне просто нужно создать поток для этого (поддерживает ли Matlab многопоточность)?

Я проверял свои идеи с помощью простой функции рисования синуса.

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

Я пока не думал о резьбе. Я рассмотрю это в ближайшее время, но любая помощь приветствуется.


person Shatnerz    schedule 04.03.2016    source источник


Ответы (1)


Во-первых, MATLAB не поддерживает многопоточность для любой графики, поэтому вам придется проявить творческий подход.

Кроме того, вы можете использовать drawnow для сброса обратного вызова и рендеринга. события, если вы пытаетесь построить график посреди своих вычислений.

Что касается знания того, когда остановиться, вы можете передать графический дескриптор кнопки своим вычислениям, и он сможет проверять значение на каждой итерации?

У меня есть пример, который использует постоянную переменную для отслеживания текущей итерация и позволяет пользователю «приостановить» вычисление, нажав на кнопку-переключатель.

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

Вы можете использовать постоянные переменные для отслеживания любых других данных, которые должны сохраняться между итерациями (а также остановками и запусками).

person Suever    schedule 04.03.2016
comment
В чем преимущество drawnow перед plot? - person Shatnerz; 04.03.2016
comment
@Shatners plot буквально просто отображает некоторые данные, но они не отображаются, пока вы не заставите MATLAB фактически отрисовать их (используя drawnow или просто не выполняя никаких вычислений). В вашем коротком примере pause имеет тот же эффект, что и drawnow, просто drawnow не требует параметра времени, и у вас больше контроля над тем, что отображается и т. д. - person Suever; 04.03.2016
comment
Спасибо за помощь. Это хорошо работает. На самом деле мне не нужно было сохранять состояние графика, но я не знал о persist. Это может быть полезно в будущем. Ваш пример полностью соответствует моим потребностям, к сожалению, блокировка все еще может быть проблемой. Я, вероятно, всегда могу вызвать расчет в конце нажатия кнопки, но я уверен, что могут возникнуть ситуации, когда кому-то нужно немного больше контроля. - person Shatnerz; 04.03.2016