Отображение нового изображения внутри существующих осей без удаления цветовой шкалы
Я работаю над графическим интерфейсом, который инициализируется путем создания нескольких axes
вместе с невидимым colorbar
для каждого (это делается для того, чтобы оси сохраняли свои предопределенные Position
) 1. Дескрипторы всех осей и цветовых полос сохранены.
Взаимодействие с пользовательским интерфейсом может привести к тому, что изображения будут нанесены на одну из осей. Мне бы хотелось, чтобы в любой момент времени отображалась только цветная полоса активных осей, соответствующим образом Visible
свойство всех цветовых полос.
У меня проблема с этим подходом, потому что я использую imagesc
обновить мои оси, и это удалит любую цветовую панель, связанную с осями, делая сохраненные маркеры недействительными.
Мой вопрос: как я могу использовать imagesc
или же image
обновить оси, связанные с цветовой шкалой, без удаления цветовой полосы?
Вот как воспроизвести эту проблему:
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
,
Некоторые идеи, которые я предполагал, предполагая, что удаление цветовой панели неизбежно (я буду реализовывать в случае, если "нормальное" решение не будет найдено):
- Связывание
DeleteFcn
на цветовую панель, которая сохраняет свои данные в некоторыхstruct
, Создание новой цветовой панели послеimagesc
закончил, затем перебирая поляstruct
и присвоение всех свойств новому объекту цветовой панели. - Проверяйте "время от времени", что все цветовые полосы существуют, используя либо
findall(hFig,'type','colorbar')
или убедитесь, что каждая из осей имеет действительныйColorbarPeerHandle
согласно приложению ниже. Воссоздайте CB, если он недействителен. - Удалите все цветные полосы, когда активны разные оси, и создайте только тот CB, который я хотел бы показать.
Приложение - Ассоциация ColorBar/Axes:
Дескриптор к цветовой панели, связанной с определенными осями
hAx
можно получить (в hg2) используя:hCb = getappdata(hAx,'ColorbarPeerHandle');
Ручка к
axes
связанный с объектом colorbarhCb
можно получить, используя 2:hAx = hCb.Axes;
1 ответ
Мне удалось придумать пару решений:
safeUpdateImage1
- На основании обходаcla(...)
через создание новогоImage
объект внутри осей после использованияhold
, Это хорошо для случаев, когдаImage
не обязательно существует в осях.safeUpdateImage2
- Следуя предложению Микколы, основываясь на обновлении существующегоImage
объект. Это хорошо для случаев, когда уже естьColorBar
иImage
связаны с осями.
Вот демонстрация обоих решений наряду с исходной проблемой:
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