多个可拖动矩形matlab:额外矩形

多个可拖动矩形matlab:额外矩形,matlab,Matlab,我正在编写一个代码来获取用户输入的多个可拖动矩形的位置。代码运行完全正常。但是,按下按钮后,代码不会向前移动,直到您再绘制一个矩形。我认为问题是pos=uint32(等待(h))语句无限期地等待另一个位置,只有在绘制另一个矩形后才考虑按钮手柄。我确实需要wait(h)语句,因为getposition函数对我不起作用。我真的很感谢你能提供的任何帮助,以下是我代码的一部分 代码: im_des=rgb2gray('image_name.jpg'); ButtonHandle = uicontrol(

我正在编写一个代码来获取用户输入的多个可拖动矩形的位置。代码运行完全正常。但是,按下按钮后,代码不会向前移动,直到您再绘制一个矩形。我认为问题是
pos=uint32(等待(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

我已经找到了在按下停止按钮后需要绘制一个额外矩形的原因,并且找到了一些可能的解决方案来解决这个问题

简言之,问题在于。。。MatLab比你快

换句话说,这是一步一步发生的:

假设您只想绘制一个矩形,然后按下“停止”按钮停止绘制

while
循环开始时的
if
语句中的条件未经验证(您尚未按下按钮),因此循环将继续

if get(ButtonHandle,'userdata')
   break ;
end
然后执行
imrect
语句

 h = imrect;
它启动矩形绘制过程:您可以绘制矩形、移动矩形、调整矩形大小等等

一旦开始绘制,就会执行下一条语句

pos = uint32(wait(h));
if get(ButtonHandle,'userdata')
h = imrect;
pos = uint32(wait(h));
wait
函数将阻止MatLab命令行,直到您在矩形上双击
退出绘图模式

如果您已经绘制了一个有效的矩形,那么下一条语句将绘制实际的矩形,将矩形的位置存储在“数组”中,并删除
imrect
对象的
handle

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
循环的新迭代将开始

再次执行第一条语句

pos = uint32(wait(h));
if get(ButtonHandle,'userdata')
h = imrect;
pos = uint32(wait(h));
如果在新的迭代开始之前,您没有那么快(并且您不可能)到达“停止”按钮并按下它,则不会验证
if
条件,因此 执行
imrect
序列

pos = uint32(wait(h));
if get(ButtonHandle,'userdata')
h = imrect;
pos = uint32(wait(h));
因为你的意图是画另一个矩形

这是在按下“停止”按钮后实际停止脚本所需的“附加”矩形

当MatLab命令行被
wait
函数阻塞时,
callback
listner不被阻塞,因此您可以按下pussh按钮,并且
userdata
的值设置为
1
然而,绘图过程已经启动

因此,您需要绘制“附加”矩形,双击退出
wait
,以便启动“while”循环的另一次迭代

此时,
if
条件最终得到验证,
break
语句停止
while
循环的执行

事情就是这样

我发现了两种可能的解决方案:第一种方案允许保持脚本“几乎”不变,第二种方案意味着改变
GUI
的概念

第一个解决方案允许您。。。比MatLab更快

如果在调用
wait
(例如
pause(3)
)后插入
pause
语句,则在新迭代开始之前,您将有3秒钟的时间到达并按下“Stop”

这允许将che
callback
setting
userdata
设置为1,并在验证循环时在
开始处设置
if
条件,从而停止脚本的执行,而无需绘制任何额外的矩形

第二种解决方案包括更改
GUI
的行为:

您可以删除
while
循环并更改
按钮回调
,以便它负责调用
imrect
并绘制矩形(实际上,您必须移动
按钮cllback
循环时
内的代码

这样,GUI的行为将是:任何时候您想要添加一个矩形,您必须按下
按钮

在这里,您可以找到这两种解决方案的脚本

请注意,为了使其运行,我对您的附加代码进行了一些附加修改:

我已删除
uint32强制转换
:轴中没有图片,默认
限制为[0 1], 如果将
pos
转换为
无符号32位整数
,pos将为[0 1 0]

我还删除了
for
循环,将
pos
存储在
数组中:实际上不需要它

解决方案#1

% 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
解决方案#2 主脚本

array=[];
axes
ButtonHandle = uicontrol('style','push','String', 'Add rect',...
   'callback','tmp=add_rect;array=[array;tmp]');
按钮回调

function pos=add_rect()
h = imrect;
pos = wait(h);
rectangle('Position', pos, 'LineWidth',1, 'EdgeColor','k')
delete(h)

希望这能有所帮助。

谢谢。我今天刚刚看到了您的解决方案。我也实现了暂停功能。非常感谢您发布了答案并尽了最大努力。不客气!这是一个非常有趣的问题,让我学到了一些新东西。