我正在编写一个代码来获取用户输入的多个可拖动矩形的位置。代码工作得很好。然而,按下按钮后,代码不会向前移动,直到您再绘制一个矩形。我认为问题是pos = uint32(wait(h));
语句无限期地等待另一个位置,并且只有在绘制另一个矩形后才会考虑按钮句柄。我确实需要wait (h)
声明,getposition
功能对我来说效果不佳。我非常感谢您提供的任何帮助,以下是我的代码的一部分。
代码:
im_des=rgb2gray('image_name.jpg');
ButtonHandle = uicontrol('style','push','String', 'STOP',...
'callback','set(gcbo,''userdata'',1,''string'',''DONE!'')', ...
'userdata',0) ;
while(1)
if get(ButtonHandle,'userdata')
break ;
end
h = imrect;
pos = uint32(wait(h));
if ~isempty(pos)
rectangle('Position', pos, 'LineWidth',1, 'EdgeColor','k');
for i=1:4
counter=counter+1;
array (counter) = pos(i);
end
delete(h);
end
end
答案 0 :(得分:1)
我已经找到了在按下“停止”按钮后需要绘制额外矩形的原因,并且我找到了几种可能的解决方案来解决问题。
简而言之,问题是...... MatLab比你快。
更确切地说,这就是一步一步发生的事情:
假设您只想绘制一个矩形,然后按“停止”按钮停止绘制。
if
循环开头的while
语句中的条件未经验证(您尚未按下按钮),因此循环继续。
if get(ButtonHandle,'userdata')
break ;
end
然后执行imrect
语句
h = imrect;
它启动矩形绘制过程:你可以绘制矩形,移动矩形,调整大小等等。
一旦开始绘图,就会执行下一个语句
pos = uint32(wait(h));
wait
函数阻止MatLab命令行,直到您在矩形上double-click
退出绘图模式
如果您绘制了一个有效的矩形,则下一个语句绘制实际的矩形,将矩形的位置存储在“数组”中,并将handle
删除到imrect
对象
if ~isempty(pos)
rectangle('Position', pos, 'LineWidth',1, 'EdgeColor','k');
for i=1:4
counter=counter+1;
array (counter) = pos(i);
end
delete(h);
end
此时您决定“停止”添加矩形并按下“停止”按钮。
这是MatLab比你更快的点。
当您移动muose的光标到达按钮时,脚本的执行将继续,并且while
循环的新迭代开始。
再次执行第一个语句
if get(ButtonHandle,'userdata')
如果您没有那么快(并且您不能)到达“停止”按钮并在新迭代开始之前推送它,则if
条件未被验证,因此
执行imrect
序列
h = imrect;
pos = uint32(wait(h));
因为你打算画另一个矩形。
这是“附加”矩形,在按下“停止”按钮后需要“看到”以实际停止脚本。
虽然wait
函数阻止了MatLab命令行,但callback
列表器不是,因此您可以按下该按钮,userdata
的值设置为{{1 }}
尽管如此,绘图过程已经激活。
因此,您需要绘制“附加”矩形,双击以退出1
,以便可以开始“while循环”的另一次迭代。
此时,最终验证wait
条件并且if
语句停止执行break
循环。
这就是发生的事情。
我找到了两种可能的解决方案:第一种解决方案允许保持脚本“几乎”不变,第二种方法意味着改变while
概念。
第一种解决方案允许你......比MatLab更快。
如果在调用GUI
之后插入pause
语句(例如wait
),则在新迭代开始之前,您将有3秒钟到达并按“停止”。
这样可以将che pause(3)
设置callback
设置为1,并在userdata
循环的开头验证if
条件,停止执行脚本无需绘制任何额外的矩形。
第二个解决方案包括更改while
:
您可以删除GUI
循环并更改while
,以便负责调用pushbutton callback
并绘制矩形(实际上,您必须移动
imrect
中while
循环内的代码。
这样GUI的行为将是:每当你想要添加一个矩形时,你必须推动pushbutton cllback
此后,您可以找到两种解决方案的脚本。
注意,我对您的其他代码进行了一些额外的修改,以使其运行:
我删除了pushbutton
:轴中没有图片,默认uint32 cast
限制为[0 1],
如果您将axes
转换为pos
,则pos将为[0 1 0 0]
此外,我已移除unsigned 32-bit integer
循环以在for
中存储pos
:实际上并不需要。
解决方案#1
array
解决方案#2 主要脚本
% Commented since in the code excerpt is not used
% im_des=rgb2gray('pdb_img_1.jpg');
ButtonHandle = uicontrol('style','push','String', 'STOP',...
'callback','set(gcbo,''userdata'',1,''string'',''DONE!'')', ...
'userdata',0) ;
% Added initialization of "array" and array_32" arrays
% array_32: stores the rectangle pos as uint32
% array: stores the rectangle pos as double (added to make the script
% running without an image on the axes)
array=[];
array_32=[];
%
while(1)
if get(ButtonHandle,'userdata')
break ;
end
% Commented type cast (default axix limit are [0 1] therefore
% pos=[ 0 1 0 0]
h = imrect;
% pos = uint32(wait(h));
pos = wait(h);
% added message display and "pause" statement to allow pressing "Stop"
% button before drawing next rectangle
disp('Press STOP within 3 sec. to stop')
pause(3)
if ~isempty(pos)
rectangle('Position', pos, 'LineWidth',1, 'EdgeColor','k')
% if needed the edge color of each rectangle can be different
% rectangle('Position', pos, 'LineWidth',1,'EdgeColor',[rand(3,1)])
%
% Commented "for loop" to store rectangle pos since it is not needed
% for i=1:4
% counter=counter+1
% "array" is built as (N x 4) matrix, each row contains the "pos" of
% a rectangle (remove ";" to store it as a (1 x N) array
array = [array ; pos]
array_32 = [array_32 ; uint32(pos)]
% end
delete(h)
end
end
按钮回拨
array=[];
axes
ButtonHandle = uicontrol('style','push','String', 'Add rect',...
'callback','tmp=add_rect;array=[array;tmp]');
希望这有帮助。