在现有轴内显示新图像,无需删除颜色条

时间:2015-11-25 00:44:12

标签: matlab matlab-figure colorbar matlab-hg2

我正在开发一个GUI,通过为每个axes创建几个colorbar以及一个不可见的Position进行初始化(这样做是为了让轴保持其预定义的1)< SUP> imagesc 。存储所有轴和颜色条的手柄。

与UI的交互可能导致图像被绘制在任何一个轴上。我希望通过适当设置所有颜色栏的Visible属性,只在任何给定时间显示活动轴的颜色条。

我遇到了这种方法的问题,因为我使用DeleteFcn来更新我的轴,这会删除与轴关联的任何颜色条,使存储的句柄无效。

我的问题是:如何使用imagescimage更新与彩条相关联的轴,而不删除彩条?

以下是如何重现此问题:

dbclear in newplot %// Needed for the code to be properly re-runnable
%// Create an example figure containing a colorbar:
figure(); imagesc(imread('cameraman.tif')); colorbar;
%// "Refreshing" the displayed image:
uiwait(msgbox('The image will now be refreshed. A breakpoint will be set in newplot.m'));
dbstop in newplot at 124 %// The line responsible for deleting the colorbar in R2015A/B
imagesc(imread('cameraman.tif'));

设置newplot.m中断点的行为:

cla(ax, 'reset', hsave);

这是(un)令人惊讶的一种未记录的方式来调用cla(带有3个参数)来保留在hsave中找到句柄的对象。

我假设彩条删除的一些想法是不可避免的(如果没有找到&#34;理智的解决方案,我会追求这个想法):

  1. 2绑定到将其数据保存到某些struct的颜色栏。在imagesc完成后创建一个新的颜色栏,然后迭代struct的字段并将所有属性分配给新的颜色条对象。
  2. 每隔一段时间检查一次&#34;&#34;所有颜色条都使用findall(hFig,'type','colorbar')存在,或者根据下面的附录验证每个轴都有一个有效的ColorbarPeerHandle。如果无效,请重新创建CB。
  3. 当不同的轴变为活动状态时删除所有颜色条,并仅创建我想要显示的CB。
  4. 附录 - ColorBar / Axes关联:

    • 可以使用以下方法获取与某个轴hAx相关联的颜色栏的句柄(在hg2中):

      hCb = getappdata(hAx,'ColorbarPeerHandle');
      
    • 可以使用 screenshot 获取与颜色条对象axes相关联的hCb的句柄:

      hAx = hCb.Axes;
      

1 个答案:

答案 0 :(得分:2)

我设法提出了几个解决方案:

  1. safeUpdateImage1 - 基于在使用cla(...)后通过在轴内创建新Image对象来规避hold。这适用于轴中不一定存在Image的情况。
  2. safeUpdateImage2 - 关注mikkola's suggestion,基于更新现有的Image对象。这适用于已经与轴关联的ColorBar Image的情况。
  3. 以下是两个解决方案与原始问题的演示:

    function [] = Problem
    dbclear in newplot %// Needed for the code to be properly re-runnable
    %// Create an example figure containing a colorbar:
    Img = imread('cameraman.tif');
    figure(); imagesc(Img); hAx = gca; colorbar;
    %// Refreshing the displayed image (comment/uncomment as needed):
    switch questdlg('Please select an image update method:','Update method selection',...
                    'Broken','Safe1','Safe2','Safe1')
      case 'Broken'
        brokenUpdateImage(hAx,255-Img);
      case 'Safe1'
        safeUpdateImage1(hAx,255-Img);
      case 'Safe2'
      safeUpdateImage2(hAx,255-Img);  
    end
    end
    
    function brokenUpdateImage(hAx,newImg)
    uiwait(msgbox('The image will now be refreshed. A breakpoint will be set in NEWPLOT'));
    dbstop in newplot at 124 %// The line responsible for deleting the colorbar in R2015A/B
    imagesc(newImg,'Parent',hAx);
    end
    
    % For cases when the only desired child is an Image and the axes contents are unknown
    function safeUpdateImage1(hAx,newImg,imgType,imgUpdateFcn)
    if nargin < 4 || isempty(imgUpdateFcn)
      imgUpdateFcn = @imagesc;
    end
    if nargin < 3 || isempty(imgType)
      imgType = 'Image';  
    end
    if strcmp(hAx.NextPlot,'replace') %// Equivalent to checking "ishold == false"
      hAx.NextPlot = 'add'; %// Equivalent to "hold on"
      %// hCurrImgs = get(hAx,'Children'); %// Deletes all types of Children
      hCurrImgs = findall(hAx,'type','Image'); %// Deletes only graphical objects of type 
                                               %// "matlab.graphics.primitive.Image"
      for ind1=1:numel(hCurrImgs)
        delete(hCurrImgs(ind1));
      end
      imgUpdateFcn(newImg,'Parent',hAx);
      if strcmpi(imgType,'Image')
        axis(hAx,'tight','ij');    
    %// 'tight' - XLimMode, YLimMode, and ZLimMode change to 'auto'. The limits automatic- 
    %//           ally update to incorporate new data added to the axes. To keep the limits
    %//           from changing when using hold on, use axis tight manual.
    %// 'ij'  —   Reverse direction. For axes with a 2-D view, the y-axis is vertical with
    %//           values increasing from top to bottom.    
      end
    end
    end
    
    %// When it's known that the axes contains at least one Image:
    function safeUpdateImage2(hAx,newImg,~,~)
    %// <Input checking code>
    hCurrImgs = findall(hAx,'type','Image');
    %// <Optional code to decide which Image child to update>
    hCurrImgs(1).CData = newImg; %// In this example, only update the "topmost" child
    end