当用户按下特定键时将控件移出循环? [英] Moving control out of a loop when user presses a specific key?

查看:54
本文介绍了当用户按下特定键时将控件移出循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在代码中使用了无限循环.

I am using an infinite loop in my code.

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

我希望我的控件在用户按下特定键(例如空格键)时退出循环. 我已经尝试在此处给出的解决方案,但是没有运气.图窗口不会打开.

I want my control to come out of the loop when a user presses a specific key, say Spacebar. I've tried the solution given here but no luck. Figure window does not open.

推荐答案

您可以选择两条路线.

1)您可以采用偶数驱动方法并为当前图形注册KeyPressFcn回调.问题是Matlab是单线程*,因此,只要您的循环连续执行某些代码,事件就不会被处理.一种解决方法是在循环中插入drawnowpause语句.这将停止主线程的执行,并处理外部事件,例如我们的按键操作.在回调中,您需要更改某些标志的状态,例如一些图形句柄的对象属性/appdata,甚至是全局变量(我建议不要这样做).这样,您便可以在循环中进行查询,并在看到标志更改时中断.

1) You can take even-driven approach and register KeyPressFcn callback for the current figure. The catch is that Matlab is single threaded*, so as long as your loop continuously executes some code, event will not be handled. A workaround would be to insert either drawnow or pause statements within your loop. That will halt the main thread execution and would process outside events, such as our key press. In the callback you would need to change the state of some flag, e.g. an object property / appdata of some graphics handle, or even a global variable (which I would advise against). You would then be able to query from within the loop and break if you see the flag changing.

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暂停要处理的字符笔划的执行.这种方法的副作用是按键后焦点移到命令窗口,并且字符也出现在命令窗口中.

2) Second approach would be to poll for CurrentCharacter. Note that it also requires you to halt execution by using pause / drawnow for the character stroke to be processed. A side-effect of this approach is that after a key press the focus moves to command window, and the character also appears there.

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中的线程:
    • EDIT elaborating on the threading in Matlab:
    • Matlab GUI组件实际上在EDT线程上运行 ,它与发生主要执行的操作是分开的(除非您不使用javaObjectEDT显式创建Java GUI对象,否则应避免)-这是GUI组件可以对执行的某些操作进行可视化反应的原因需要与主执行线程同步,例如在单击它时在视觉上更改按钮状态.但是要真正使回调运行并更改执行线程内工作空间的状态,您需要让Matlab同步这两个线程.这就是pause/drawnow的作用-它会暂停您在执行线程上所做的所有操作,从而允许您的GUI回调同时执行. drawnow将在执行返回到原始代码块之前清除整个待处理队列,而pause可能仅处理某些回调,直到时间用完.如果将pause参数设置为一秒钟的很小一部分并执行很多操作-不会全部处理,您可能会观察到这一点.

      Matlab GUI components actually run on EDT thread, which is separate to the one where the main execution is happening (unless you create java GUI objects explicitly without using javaObjectEDT, which you should avoid) - this is what allows GUI components to visually react on some actions you take which do not require synchronization with the main execution thread, like visually changing button state when clicking on it. But to actually get the callback to run and change the state of your workspace inside the execution thread, you need to let Matlab synchronize the two threads. This is what pause/drawnow helps to do - it halts whatever you've been doing on the execution thread which allows your GUI callbacks to execute in the meantime. drawnow would clear the whole pending queue before returning execution to your original code block, while pause will potentially only process some of the callbacks until the time runs out. You may observe this if you set pause argument to a tiny fraction of a second and make lots of actions - not all will be processed.

      您可能会注意到在不同的Matlab版本之间,行为上有一些细微的变化-随着时间的推移,这两个线程似乎变得更加独立.令人惊讶的是,很少有官方信息可用-大多数基于经验和分散在Matlab中央的各种答案,例如这个那个,显然是很棒的文章在UndocumentMatlab上,就像上面链接的一样.

      You may notice some slight changes in behavior between different Matlab releases - the two threads seem to become slightly more independent over time. There is surprisingly little official information available on this - most of it is based on experience and various answers scattered across Matlab central, like this and that, and obviously fantastic articles on the UndocumentMatlab, like the one linked above.

      这篇关于当用户按下特定键时将控件移出循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆