当用户按下特定键时,将控制移出循环?

时间:2016-05-18 18:34:57

标签: matlab

我在代码中使用无限循环。

while 1
% many statements/computation...
...
...
end

当用户按下特定键时,我想让我的控件退出循环,比如空格键。 我已经尝试了here给出的解决方案,但没有运气。图窗口无法打开。

2 个答案:

答案 0 :(得分:2)

您可以选择两条路线。

1)您可以采用偶数驱动方法并为当前数字注册KeyPressFcn回调。问题是Matlab是单线程*,所以只要你的循环连续执行某些代码,就不会处理事件。解决方法是在循环中插入drawnowpause语句。这将停止主线程执行并处理外部事件,例如我们的按键。在回调中,您需要更改某个标志的状态,例如一些图形句柄的对象属性/ appdata,甚至是全局变量(我建议反对)。然后,您可以在循环内查询并查看标志是否发生变化。

function test()
    hFig = figure();
    setappdata(hFig, 'space_pressed', false);
    set(hFig, 'KeyPressFcn', @keyPressedFcn);

    while true
        A = randn(10000); % doing some stuff

        pause(0.01);
        flag = getappdata(hFig, 'space_pressed');
        if flag
            break;
        end
        fprintf('Still running...\n');
    end
    fprintf('Finished!\n');
end

function keyPressedFcn(hFig, event)
    fprintf('Pressed character: "%s"...\n', event.Character);
    if strcmp(event.Character, ' ')
        setappdata(hFig, 'space_pressed', true);
    end
end

示例输出:

>> test
Still running...
Still running...
Pressed character: "h"...
Still running...
Still running...
Pressed character: " "...
Finished!

2)第二种方法是轮询CurrentCharacter。请注意,它还要求您使用pause / drawnow暂停执行以处理字符笔划。这种方法的副作用是按下按键后焦点移动到命令窗口,角色也会出现在那里。

function test()
    hFig = figure();
    set(hFig, 'CurrentCharacter', '^'); % some other character
    drawnow();

    while true
        A = randn(10000); % doing some stuff

        pause(0.01);
        char = get(hFig, 'CurrentCharacter');
        if strcmp(char, ' ')
            break;
        end
        fprintf('Still running...\n');
    end
    fprintf('Finished!\n');
end
  • 编辑详细阐述了Matlab中的线程:

Matlab GUI组件实际上是run on EDT thread,它与主执行发生的组件分开(除非你明确创建java GUI对象而不使用javaObjectEDT,你应该避免) - 这就是允许GUI组件在视觉上对您执行的某些操作做出反应,这些操作不需要与主执行线程同步,例如在单击时可视地更改按钮状态。但是要实际获得回调以在执行线程内运行并更改工作区的状态,您需要让Matlab同步两个线程。这就是pause / drawnow有助于做的事情 - 它会停止你在执行线程上做的任何事情,这允许你的GUI回调在此期间执行。 drawnow会在将执行返回到原始代码块之前清除整个挂起队列,而pause可能只会处理一些回调,直到时间用完为止。如果将pause参数设置为一小部分时间并进行大量操作,您可能会观察到这一点 - 并非所有操作都会被处理。

您可能会注意到不同Matlab版本之间的行为略有变化 - 两个线程似乎随着时间的推移变得更加独立。令人惊讶的是,关于此的官方信息很少 - 大多数是基于经验和分散在Matlab中心的各种答案,如thisthat,以及UndocumentMatlab上的精彩文章,如链接的上方。

答案 1 :(得分:-2)

为什么不这样:

ended = false
while !ended 
    if pressed_spacebar 
        ended = true 

如果你不能改变你的循环条件,你可以使用break指令,但这不是一个好的编程习惯:)