4

我正在开发一个 GUI,该 GUI 通过创建几个axes以及colorbar每个不可见来初始化(这样做是为了使轴保持其预定义Position1。存储所有轴和颜色条的句柄。

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

我对这种方法有疑问,因为我正在使用imagesc更新我的轴,这会删除与轴关联的任何颜色条,从而使存储的句柄无效。

我的问题是:如何在不删除颜色条的情况下使用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);

这是(未)令人惊讶的是一种未记录的调用方式cla(使用 3 个参数),它保留了在hsave.


我假设删除颜色条是不可避免的一些想法(如果找不到“理智”的解决方案,我将继续这样做):

  1. 将 a 绑定DeleteFcn到将其数据保存到 some 的颜色栏struct。完成后创建一个新的颜色imagesc条,然后遍历 的字段struct并将所有属性分配给新的颜色条对象。
  2. 根据下面的附录,“每隔一段时间”检查所有颜色findall(hFig,'type','colorbar')条是否存在或验证每个轴是否有效。ColorbarPeerHandle如果无效,重新创建 CB。
  3. 每当不同的轴激活时删除所有颜色条并仅创建我想显示的 CB。

附录 - ColorBar/Axes 关联:

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

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

     hAx = hCb.Axes;
    
4

1 回答 1

2

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

  1. safeUpdateImage1- 基于通过在使用后在轴内cla(...)创建新对象的规避。这适用于轴中不一定存在的情况。ImageholdImage
  2. safeUpdateImage2- 根据mikkola 的建议,基于更新现有Image对象。这适用于已经存在 aColorBar aImage与轴关联的情况。

这是与原始问题一起演示的两种解决方案:

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
于 2015-11-25T13:08:35.173 回答