我创建了一个基于外部.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
当用户更改“控件”面板中的任何值或按下“Break”按钮时,我想停止计算并清除计算出的数组。
我怎么能编码?
答案 0 :(得分:0)
我能想出的最佳解决方案是将您的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
答案 1 :(得分:0)
在MATLAB中,无法通过其他函数来中断一个函数,例如比如说以编程方式将CTRL-C注入到另一个正在运行的函数中,而无需修改要中断的函数。
您可以得到的最接近的结果是修改模拟器代码以定期执行回调。这就是我通过仿真代码将其集成到GUI中的方式。 IMO,这是一个干净的解决方案,还可以处理MEX文件。
将其视为模拟器代码的进度回调。
模拟器可能会定期(例如每秒或在第i步完成时)调用某个百分比参数来指示完成程度。
如果您修改模拟器代码以在回调返回false的情况下停止模拟,则可以实现所需的功能。同时,这是对您的模拟器代码的最小侵入。提供一个虚拟回调,它将独立运行。
GUI伪代码:
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 )
SIMULATOR伪代码:
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"