【问题标题】:How to make a function non-blocking? Dynamic plotting in Matlab GUI如何使函数非阻塞? Matlab GUI 中的动态绘图
【发布时间】:2016-03-04 18:51:50
【问题描述】:

使用 Matlab 已经有一段时间了,直到现在我还没有将它用于任何 GUI 创建。我的目标是有一个我可以按下的按钮,然后在计算结果时绘制结果。该按钮应根据发生的情况在“开始”和“停止”之间切换。这些结果经过多次迭代收集,每次迭代都会给出另一个数据点。

我的解决方案是将轴传递给进行计算的函数,然后该函数可以绘制到轴上。这可行,但是在发生这种情况时,按钮不会切换到“停止”,直到绘图完成后。我可以使功能非阻塞吗?我什至要这样做是最好的方法吗?如何使用“停止”按钮停止计算?我只需要为此创建一个线程(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

直到现在我还没有想到线程。我会尽快调查,但感谢所有帮助。

【问题讨论】:

    标签: matlab user-interface matlab-guide matlab-gui


    【解决方案1】:

    首先,MATLAB 不对任何图形进行多线程处理,因此您必须发挥创造力。

    此外,如果您尝试在计算过程中进行一些绘图,则需要使用 drawnow 刷新回调和渲染事件。

    至于知道什么时候停止,你也许可以将按钮的图形句柄传递给你的计算,它可以检查每次迭代的值?

    我有一个使用persistent variable 来跟踪当前迭代并允许用户通过取消单击切换按钮来“暂停”计算的示例。

    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
    

    您可以使用持久性变量来跟踪需要在迭代之间(以及停止和启动)保持的任何其他数据。

    【讨论】:

    • drawnowplot 相比有什么优势?
    • @Shatners plot 实际上只是绘制了一些数据,但直到您强制 MATLAB 实际 绘制 它才会呈现(使用 drawnow 或只是不做任何事情计算)。在您的简短示例中,pausedrawnow 具有相同的效果,只是drawnow 不需要时间参数,您可以更好地控制渲染的内容等。
    • 感谢您的帮助。这很好用。我实际上并不需要保存情节的状态,但我不知道persist。将来可能会有用。你的例子完全符合我的需要,不幸的是阻塞仍然是一个问题。我可能总是可以在按钮按下结束时进行计算调用,但我确信可能会出现有人需要更多控制的情况。
    猜你喜欢
    • 2017-08-31
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 2015-03-31
    • 2018-10-13
    • 1970-01-01
    • 2012-02-20
    • 2015-11-15
    相关资源
    最近更新 更多