【问题标题】:MATLAB - AppDesigner: Interrupt a loop with GUIMATLAB - AppDesigner:使用 GUI 中断循环
【发布时间】:2018-08-07 12:19:10
【问题描述】:

我创建了一个基于外部 .m 文件计算轨迹的 GUI。

当用户按下“计算”按钮时,通过按钮的回调函数调用外部 .m 函数文件:

% calculateBtn button pushed function
function calculate(app)
    numSteps = app.stepSlider.Value;

    app.omega = app.omegaSpin.Value;
    app.phid = app.phi.Value;

    app.x0 = app.x0Spin.Value;
    app.y0 = app.y0Spin.Value;

    app.u0 = app.u0Spin.Value;
    app.v0 = app.v0Spin.Value;

    set(app.calculateBtn, 'Enable', 'off')
    set(app.showBtn, 'Enable', 'off')

    [app.Xc, app.Xi, app.C, T, f]=coriolis_traj(app.x0, app.y0, app.u0, app.v0, app.phid, numSteps);

    app.fEdit.Value = num2str(f);
    app.tEdit.Value = num2str(T);

    set(app.calculateBtn, 'Enable', 'on')

    if length(app.Xc)>1
        set(app.showBtn, 'Enable', 'on')
    else
        set(app.showBtn, 'Enable', 'off')
    end
end

外部文件由计算的主循环组成。

    while 1
    % Counters
    i = i + 1;
    t = t + Dt;
    theta = theta + Omega * Dt;

    % Parcel's position
    % on the inertial frame
    x1 = x0 + Dt*u0;
    y1 = y0 + Dt*v0;

    % Parcel's position translated to the
    % rotating frame
    xc1 = x1*cos(theta)+y1*sin(theta);
    yc1 = x1*sin(theta)+y1*cos(theta);

    x(i) = x1 ; y(i) = y1;
    xc(i) = xc1 ; yc(i) = yc1;

    x0 = x1 ; y0 = y1;

    [in] = inpolygon(xc,yc,xv,yv);
    if ~in(i) > 0
        break;
    end
end

当用户更改“控件”面板中的任何值或按下“中断”按钮时,我想停止计算并清除计算数组。

我该如何编码?

【问题讨论】:

  • 查看interruptible attribute of callbacks(与 BusyAction 属性合作)
  • @Wolfie 我找不到可以在回调中使用可中断属性的方法。我不知道我可以通过哪种方式来实现。

标签: matlab user-interface matlab-app-designer


【解决方案1】:

我能想到的最佳解决方案是将您的 while 循环带入您的 GUI 回调中。 while 循环的内部代码可以保存在单独的外部文件中,但引入循环将使您能够完全控制它,并且更容易中断。唯一的限制是它必须不那么“紧密”......它必须包含一个小的pause(如果后面跟一个drawnow()调用更好),以便主GUI线程可以有时间处理应用程序消息.

这是你的回调代码:

% Computation Callback
function Button1_Callback(obj,evd,handles)
    obj.Enable = 'off';            % disable this button
    handles.Button2.Enable = 'on'; % enable the interruption button
    handles.stop = false;          % the control variable for interruption

    while (true)
        % call your external function for running a computational cycle
        res = myExternalFunction(...);

        % refresh the application handles
        handles = guidata(obj);

        % interrupt the loop if the variable has changed
        if (handles.stop)
            break;
        end

        % this allows the loop to be interrupted
        pause(0.01);
        drawnow();
    end

    obj.Enable = 'on';
end

% Interruption Callback
function Button2_Callback(obj,evd,handles)
    obj.Enable = 'off';            % disable this button

    handles = guidata(obj);
    handles.stop = true;
end

【讨论】:

    【解决方案2】:

    在 MATLAB 中没有办法通过另一个函数中断一个函数,例如比如说以编程方式将 CTRL-C 注入另一个正在运行的函数中,而不修改要被中断的函数。

    最接近的方法是修改模拟器代码以定期执行回调。这就是我通过模拟代码将其集成到 GUI 中的方式。 IMO 这是一个干净的解决方案,也适用于 MEX 文件。

    将其视为您的模拟器代码的进度回调。

    它可以由模拟器定期调用(例如每秒,或在完成第 i 步时),并带有一些百分比参数来指示完成程度。

    如果您修改模拟器代码以在回调返回 false 的情况下停止模拟,您就可以实现您想要的。同时,这对您的模拟器代码的侵入性最小。提供一个虚拟回调,它将独立运行。

    图形用户界面伪代码:

    function button_cancel_Callback(hObject, eventdata, handles)
    global cancel_pressed;
    cancel_pressed = true;
    
    function dostop = callback( progress, handles )
    <show progress>( handles.<XXX>, progress );
    global cancel_pressed;
    if cancel_pressed
       dostop = true;
    else
       dostop = false;
    end
    
    function button_run_simulation_Callback(hObject, eventdata, handles)
    global cancel_pressed;
    cancel_pressed = false;
    
    <simulator function>( ..., @callback, handles )
    

    模拟器伪代码:

    function <simulator function>( ..., callback, callback_param )
    while ...  % main loop
      if ~isempty(callback) && ~callback( progress, callback_param )
          error("canceled-by-user") % could also be something more elaborate
    end
    return "simulation completed"
    

    【讨论】:

      猜你喜欢
      • 2011-05-30
      • 2011-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多