【问题标题】:Breaking from for loop in MATLAB GUI在 MATLAB GUI 中打破 for 循环
【发布时间】:2011-05-30 04:14:48
【问题描述】:

我在 MATLAB 的 GUI 的打开函数中有一个 for 循环,我正在尝试使用回调按钮来中断循环。我是 MATLAB 新手。这是我的代码:

%In the opening function of the GUI
handles.stop_now = 0;
for i=1:inf
   if handles.stop_now==1
      break;
   end
end


% Executes on button press 
function pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to end_segmenting_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles.stop_now=1;
guidata(hObject, handles);

出于某种原因,尽管使用句柄定义了变量,但按下按钮时循环不会中断。有谁知道发生了什么?谢谢。

【问题讨论】:

    标签: user-interface matlab


    【解决方案1】:

    我在这里看到两个潜在的问题。

    首先:变量handles 不是引用,在控制流退出pushbutton_Callback 后设置handles.stop_now=1; 将“丢失”。使用guidataother approaches 存储和检索数据。

    Second problem: 使用函数drawnow()。请参阅this article of Yair Altman 以获得很好的解释。

    总结:MATLAB 图形是 Java Swing 和 IO 操作(如按下按钮)发生在一个特殊线程 - 事件调度线程 (EDT) 上。调用drawow();刷新事件队列并更新图形窗口。

    【讨论】:

    • 我正在使用 guidata,并且我已检查以确保在 pushbutton_Callback 之外更新了 handles.stop_now(即,我知道它不会丢失),但由于某种原因,它在for 循环...
    【解决方案2】:

    您遇到的问题是传递给opening functionhandles 的值结构固定为调用打开函数时的任何值。您永远不会检索由pushbutton_Callback 更新的新结构。您可以通过在循环中调用 GUIDATA 来检索新结构。以下是我建议您尝试编写循环的方法:

    handles.stop_now = 0;  %# Create stop_now in the handles structure
    guidata(hObject,handles);  %# Update the GUI data
    while ~(handles.stop_now)
      drawnow;  %# Give the button callback a chance to interrupt the opening function
      handles = guidata(hObject);  %# Get the newest GUI data
    end
    

    更大的 GUI 设计问题...

    根据您评论中关于您尝试使用 GUI 完成什么的附加描述,我认为可能有更好的设计方法。您可以取消循环和停止按钮,并在您的 GUI 中添加一个“添加 ROI”按钮,而不是让用户重复输入 ROI 的连续循环,然后他们必须按下按钮停止。这样,用户在想要添加另一个 ROI 时只需按一个按钮。您可以先将打开函数中的 for 循环替换为以下初始化:

    handles.nROIs = 0;  %# Current number of ROIs
    handles.H = {};  %# ROI handles
    handles.P = {};  %# ROI masks
    guidata(hObject,handles);  %# Update the GUI data
    

    然后您可以将按钮的回调替换为以下内容:

    function pushbutton_Callback(hObject,eventdata,handles)
    %# Callback for "Add new ROI" button
      nROIs = handles.nROIs+1;  %# Increment the number of ROIs
      hROI = imfreehand;  %# Add a new free-hand ROI
      position = wait(hROI);  %# Wait until the user is done with the ROI
      handles.nROIs = nROIs;  %# Update the number of ROIs
      handles.H{nROIs} = hROI;  %# Save the ROI handle
      handles.P{nROIs} = hROI.createMask;  %# Save the ROI mask
      guidata(hObject,handles);  %# Update the GUI data
    end
    

    【讨论】:

    • 我明白了,所以关键是在循环中调用 GUIDATA。我现在实际上遇到了另一个问题。我正在使用 for 循环从带有 imagefreehand 的图像中捕获 ROI。对于 i=1:inf 绘制的句柄 = guidata(hObject);如果handles.stop_now==1 中断;结束句柄.H{i} = imfreehand;句柄.P{i}=句柄.H{i}.createMask;问题是,一旦我按下按钮,我只能在选择一个额外的手绘区域后退出循环。我怎样才能解决这个问题?
    • 在您的实现中,break 退出循环,控制流转到imfreehand()。因此,您应该使用return 而不是break
    • 感谢所有帮助。问题是,我正在使用该程序来分割生物图像。在一张图像中,我可能需要分割多达 20 个不同的对象,所以我不希望用户每次需要添加额外的 ROI 时都按下按钮。我只是想知道是否有任何方法可以解决我在当前设置中遇到的问题。
    猜你喜欢
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多