Matlab:实现 CTRL+C 的功能,但在代码中
Posted
技术标签:
【中文标题】Matlab:实现 CTRL+C 的功能,但在代码中【英文标题】:Matlab: implementing what CTRL+C does, but in the code 【发布时间】:2012-04-05 17:21:01 【问题描述】:我希望能够通过在代码中调用命令来终止我当前正在运行的脚本(函数)。 Return 只会终止当前函数而不是整个脚本。因此返回不是唯一的。
我正在寻找的是一个与 CTRL + C 完全相同的命令。 我已经看到了这个:how to stop execution 并注意到那里也没有人为这个问题提供正确的答案。
最后我想在关闭图形时终止整个正在运行的脚本:
hFig = figure('CloseRequestFcn',@closeHandler);
.
.
.
function closeHandler (src,evnt)
CTRL+C <--- I am looking for such a command
end
附言。 function error() 也不起作用:试试这个:
function terminateInCode()
hFig = figure('CloseRequestFcn',@closeHandler);
while(1)
plot(10*rand,10*rand,'+');
pause(0.1);
end;
function closeHandler (src,evnt)
delete(hFig);
error('program terminated!');
end
end
【问题讨论】:
如果你能解释你想要这种行为的原因会有所帮助。目前,这在 matlab 中是未记录/不支持/不可撤销的,那么您为什么要这样做呢?是什么问题促使您采用这种不可行的解决方案? 我想在关闭图形时终止整个运行脚本。 【参考方案1】:这是一个基于yuk's answer 的示例函数。组件包括:
确保命令窗口具有焦点以接收 CTRL+C 在中断发生后使用计时器释放 CTRL+C 使用 Java 机器人按 CTRL+C示例函数如下:
function terminateExecution
%terminateExecution Emulates CTRL-C
% terminateExecution Stops operation of a program by emulating a
% CTRL-C press by the user.
%
% Running this function
%
%Example:
%for ix = 1:100
% disp(ix)
% if ix>20
% terminateExecution;
% end
%end
%1) request focus be transferred to the command window
% (H/T http://undocumentedmatlab.com/blog/changing-matlab-command-window-colors/)
cmdWindow = com.mathworks.mde.cmdwin.CmdWin.getInstance();
cmdWindow.grabFocus();
%2) Wait for focus transfer to complete (up to 2 seconds)
focustransferTimer = tic;
while ~cmdWindow.isFocusOwner
pause(0.1); %Pause some small interval
if (toc(focustransferTimer) > 2)
error('Error transferring focus for CTRL+C press.')
end
end
%3) Use Java robot to execute a CTRL+C in the (now focused) command window.
%3.1) Setup a timer to relase CTRL + C in 1 second
% Try to reuse an existing timer if possible (this would be a holdover
% from a previous execution)
t_all = timerfindall;
releaseTimer = [];
ix_timer = 1;
while isempty(releaseTimer) && (ix_timer<= length(t_all))
if isequal(t_all(ix_timer).TimerFcn, @releaseCtrl_C)
releaseTimer = t_all(ix_timer);
end
ix_timer = ix_timer+1;
end
if isempty(releaseTimer)
releaseTimer = timer;
releaseTimer.TimerFcn = @releaseCtrl_C;
end
releaseTimer.StartDelay = 1;
start(releaseTimer);
%3.2) Press press CTRL+C
pressCtrl_C
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function pressCtrl_C
import java.awt.Robot;
import java.awt.event.*;
SimKey=Robot;
SimKey.keyPress(KeyEvent.VK_CONTROL);
SimKey.keyPress(KeyEvent.VK_C);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function releaseCtrl_C(ignore1, ignore2)
import java.awt.Robot;
import java.awt.event.*;
SimKey=Robot;
SimKey.keyRelease(KeyEvent.VK_CONTROL);
SimKey.keyRelease(KeyEvent.VK_C);
【讨论】:
我建议你把这个上传到文件交换。当你这样做时让我知道,以便我可以使用正确属性的文件。 代码不适用于嵌套循环 (matlab 2011a) - 检查此代码:for j = 1 : 10 for k = 1 : 10 if j > 2 && k > 2 terminateExecution; disp(['j = ' num2str(j)]); disp(['k = ' num2str(k)]); end end end
@memyself:即使在您的示例中,该功能也确实有效。只是响应需要一些时间,而且似乎 100 个循环是不够的。 j
和 k
都尝试 100。就我而言,它终止了j=19
和k=33
的代码。
看起来最初发布的功能仅在命令窗口具有焦点时才有效。否则 CTRL+C 将被发送到一个不会停止执行的窗口,请参阅编辑以进行修复。 “keyRelease”函数并不总是执行,所以我有时也会卡住 CTRL 键。还不确定是否可以解决此问题。
@Persuit - 干得好!请参阅我的替代方案以获得更简单的方法来规避所有这些问题......但它是通过受保护的方法来实现的。 :)【参考方案2】:
不确定它是否会起作用,只是一个想法。如何在 MATLAB 中模拟键盘按键?
你可以试试java.awd.Robot
:
import java.awt.Robot;
import java.awt.event.*;
SimKey=Robot;
SimKey.keyPress(KeyEvent.VK_CONTROL);
SimKey.keyPress(KeyEvent.VK_C);
或WScript.Shell and SendKeys。
【讨论】:
-1。这会使我的 Mac 上的 control 和 c 键无法使用,并且在我的 Windows 机器上不起作用(两者都为 R2011a)。如果赏金默认,我宁愿看到它朝着@Persuit 的修改和冲出这个想法。 @MattB.:首先我不希望赏金只是为了一个想法。我相信 OP 可以为他最喜欢的任何答案分配赏金,我希望他会这样做,而不是让它默认。看不到你投反对票的理由。顺便说一句,我确实赞成 Persuit 的答案。 这是个好主意。 :) 但它不完整且有问题。请不要亲自投票;我在评论中留下了三个原因。我对赏金系统的理解是,如果提供者不分配它,它默认为最高投票的答案。这可能是不正确的(?),但我关于键卡在 Mac 支架上的观点。很简单——我认为答案的投票顺序应该与现状不同。 Persuit的答案比你的更完整。 Downvoting 有助于实现这一点。如果我对这里的礼仪理解有误,请见谅。【参考方案3】:不幸的是,似乎无法做到:
Mathworks
除了使用键盘的 之外,无法在 MATLAB 中以编程方式发出 Ctrl+C >Ctrl+C组合。
作为替代方案,您可以使用 ERROR 命令强制执行将退出代码的错误。例如:
error('Program terminated for a specific reason')
【讨论】:
【参考方案4】:这是一种替代方法,它使用未记录的 Matlab 调用将键事件直接放入命令窗口。这样做的方法受到保护;这使用反射来解除保护。
与@yuk 和@Persuit 的答案不同,这似乎没有控制键粘连的问题。此外,它将始终直接发布到命令窗口,没有任何竞争条件或其他确保焦点的问题。而且,我认为它会确定性地触发——它会立即执行。
需要注意的是,它使用未记录的调用来检索命令窗口实例的句柄。这因版本而略有不同,因为它取决于窗口框架布局。 Yair Altman (undocumentedmatlab.com) 在文件交换方面的一些工作具有更强大的功能,可以以更一般的方式抓住它;此代码应该适用于大多数现代版本的 Matlab(在 R2011a,Mac 和 Win 上测试)。
function interrupt
import java.awt.event.KeyEvent
import java.util.Calendar
import java.lang.reflection.*
cmdwin = handle(com.mathworks.mde.cmdwin.CmdWin.getInstance().getComponent(0).getComponent(0).getComponent(0),'CallbackProperties');
argSig = javaArray('java.lang.Class',1);
argSig(1) = java.lang.Class.forName('java.awt.event.KeyEvent');
method = cmdwin.getClass().getDeclaredMethod('processKeyEvent',argSig);
method.setAccessible(true);
cal = Calendar.getInstance();
args = javaArray('java.lang.Object',1);
args(1) = KeyEvent(cmdwin,KeyEvent.KEY_PRESSED,cal.getTime().getTime(),KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_C,KeyEvent.CHAR_UNDEFINED);
method.invoke(cmdwin,args);
【讨论】:
应该如何调用它?function tempFigure() hFig = figure('CloseRequestFcn',@closeHandler);而(1)情节(10 *兰德,10 *兰德,'+');暂停(0.1);结尾;函数closeHandler(src,evnt)删除(hFig);打断;结束结束 它关闭了脚本,但显然没有返回命令提示符(在命令窗口中),或者我没有正确使用它哈? 哦,有趣。是的,您调用它是正确的,但是由于它是在关闭函数中执行的,因此错误并被中止的是关闭函数。这是 Matlab 中固有存在但很少发生的竞争条件(尝试在关闭 fcn 的暂停期间手动键入 ctrl-c)。因此,在这种情况下,机器人的轻微延迟实际上对您有所帮助。 谢谢!根据我的经验,这似乎比@pursuit 建议的版本更强大。【参考方案5】:您可以使用函数error
。您将返回 matlab。
它会产生错误,但这也是在 matlab 脚本中按CTRL+C
时通常会发生的情况。
你应该添加一些类似error('Interrupted by user');
的消息
【讨论】:
我想你的意思是error
,对吧?
谢谢。我不知道为什么,我以为他在 mex 文件中。
函数错误也不起作用。有关更多信息,我编辑了问题并发布了代码以了解原因。【参考方案6】:
这并不完全是您所要求的,但考虑到您的示例,您的问题可以这样解决:
function terminateInCode()
hFig = figure('CloseRequestFcn',@closeHandler);
stop=0;
while(~stop)
plot(10*rand,10*rand,'+');
pause(0.1);
end;
function closeHandler (src,evnt)
delete(hFig);
stop=1;
end
end
【讨论】:
【参考方案7】:试试 return 语句。它会把你赶出一个功能。
如果你想完全终止它,你需要使用 ERROR。
如果它真的那么灾难性,你总是可以使用 EXIT。
【讨论】:
请阅读整篇文章。我已经提到错误不起作用 @Cgraphics 我阅读了整篇文章。是你的系统有问题,而不是命令。以上是关于Matlab:实现 CTRL+C 的功能,但在代码中的主要内容,如果未能解决你的问题,请参考以下文章