如何在不向函数添加中断检查的情况下从 GUI 回调中断函数? (MATLAB)

发布于 2024-12-06 01:32:35 字数 1057 浏览 2 评论 0原文

因此,我有一个基本上允许用户迭代处理数据的 GUI。因此,有一个开始/停止按钮和一个显示数据当前状态的显示器。当您单击开始按钮时,回调函数将调用如下所示的数据处理函数:

function result = process_data(data)
    result = 0;
    for big_loop=big_start:big_end
        for small_loop=small_start:small_end
            result = result+data; %in reality just some fancier matrix ops
        end
    end

我的问题是如何实现停止按钮的回调,以便它在小循环的当前迭代之后从 process_data 返回。

现在,我通过将 process_data 代码修改为如下所示来做到这一点:

    function result = process_data_new(data)
        result = 0;
        for big_loop=big_start:big_end
            for small_loop=small_start:small_end
                result = result+data; %in reality just some fancier matrix ops
%new code start -----------------
                if interrupt_flag
                    return;
                end
%new code end -------------------- 
            end
        end

但是,我真的希望从 GUI 端处理中断,这样我的代码就不会充斥着中断检查(我的真实代码将涉及这种事情< em>经常,用户有时需要更改 process_data 函数)。

这可能吗?我想这将涉及使所有循环变量成为“可观察”属性,然后等待small_loop更改,但我无法弄清楚如何实现回调的细节。

So, I've a GUI that basically allows the user to iteratively process data. Thus, there is a start/stop button and a display that shows the current state of the data. When you click the start button, the callback function calls the data processing function shown below:

function result = process_data(data)
    result = 0;
    for big_loop=big_start:big_end
        for small_loop=small_start:small_end
            result = result+data; %in reality just some fancier matrix ops
        end
    end

My problem is how to implement the stop button's callback so that it returns from process_data after the current iteration of the small loop.

Right now I do this by modifying the process_data code to be as follows:

    function result = process_data_new(data)
        result = 0;
        for big_loop=big_start:big_end
            for small_loop=small_start:small_end
                result = result+data; %in reality just some fancier matrix ops
%new code start -----------------
                if interrupt_flag
                    return;
                end
%new code end -------------------- 
            end
        end

However, I really want the interruption to be handled from the GUI's end so my code isn't littered with interrupt checks (My real code would involve this kind of thing very often, and the user would sometimes need to change the process_data function).

Is this possible? I imagine it would involve making all of the looping variables 'observable' properties, and then waiting for small_loop to change, but I can't figure out details of how to go about implementing the callback.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

沫离伤花 2024-12-13 01:32:35

可能这会有所帮助:

有一个“停止”按钮,在其回调中将标志设置为 true。

在较小的循环中(即忙于循环的另一个回调),它将在其(小)循环的顶部(或底部)检查此标志。

如果该标志设置为 true,它会立即使其变为 false,并终止整个循环并返回。 (在循环中添加一个检查以检查是否设置了此标志)

因此,如果命中发生在最后一次检查之后,则用户在点击 STOP 后最多需要等待一次较小的迭代才能完成。

回调会互相中断,所以上面的方法有效。

该标志在 userData 缓冲区中设置,并由其他回调每次从那里读取。

此片段来自一个示例的代码我有

一个小循环示例

 function status= output(t,x,~,data)
         %called by ode45 after each step. Plot the current
         %pendulum position for simulation

         userData = get(data.handles.figure1, 'UserData');
         if userData.stop
             status=true;
             g_status =true;
         else
             status = false;
             .... do real work
         end
     end

“运行”按钮回调

% --- Executes on button press in run_btn.
function run_btn_Callback(hObject, eventdata, handles)
% hObject    handle to run_btn (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

[data,status] = parse_input(handles);
if not(status)
     return;
end
.....
userData.stop = false;
set(handles.figure1, 'UserData',userData);
...

停止按钮回调

% --- Executes on button press in reset_tag.
function reset_tag_Callback(hObject, eventdata, handles)
% hObject    handle to reset_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


data = get(handles.figure1, 'UserData');
data.stop = true;
set(handles.figure1, 'UserData',data);
.....

may be this helps:

have a button 'stop', in its callback, set a flag to true.

in the smaller loop (i.e. the other callback which busy in a loop), it will check this flag at the top (or bottom) of its (small) loop.

If the flag is set true, it makes it false right away and terminate the overall loop and returns. (add a check in your loop to check if this flag is set)

So, the most the user has to wait after hitting STOP is for one smaller iteration to complete if the hit happened just after the last check.

callbacks interrupt each others, so the above works.

The flag is set in userData buffer and read from there by the other callback each time.

This snippets code from one example I have

the small loop example

 function status= output(t,x,~,data)
         %called by ode45 after each step. Plot the current
         %pendulum position for simulation

         userData = get(data.handles.figure1, 'UserData');
         if userData.stop
             status=true;
             g_status =true;
         else
             status = false;
             .... do real work
         end
     end

the 'run' button callback

% --- Executes on button press in run_btn.
function run_btn_Callback(hObject, eventdata, handles)
% hObject    handle to run_btn (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

[data,status] = parse_input(handles);
if not(status)
     return;
end
.....
userData.stop = false;
set(handles.figure1, 'UserData',userData);
...

stop button callback

% --- Executes on button press in reset_tag.
function reset_tag_Callback(hObject, eventdata, handles)
% hObject    handle to reset_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


data = get(handles.figure1, 'UserData');
data.stop = true;
set(handles.figure1, 'UserData',data);
.....

落在眉间の轻吻 2024-12-13 01:32:35

如果你有并行计算工具箱,那么你可以创建一个任务。

否则,我认为如果不添加您建议的控制流是不可能的,因为没有其他方法可以创建处理线程并从 UI 中停止它。

If you have the parallel computing toolbox, then you can create a Task.

Otherwise, I don't think it's possible without adding the control flow you suggest since there's no other way of creating a processing thread and stopping it from your UI.

黒涩兲箜 2024-12-13 01:32:35

您基本上想要的是在用户按下“停止”按钮后终止process_data。不幸的是,这是不可能的,因为 matlab 中没有真正的线程。因此,您唯一的解决方案就是您自己实施的解决方案。

what you basically want is to kill the process_data once the user presses the 'stop' button. Unfortunately, this is not possible because there are no real threads in matlab. Therefore, your only solution is the one you've implemented yourself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文