链接MATLAB轴的不同属性

时间:2015-01-28 23:09:51

标签: matlab plot

是否可以将一个MATLAB轴的'XLim'属性链接到另一个轴的'YLim'属性?我查看了linkaxeslinkprop但据我所知,他们只能链接相同的属性,例如一个轴'XLim'到另一个轴'XLim',依此类推。

使用MATLAB 2014b。谢谢!

5 个答案:

答案 0 :(得分:2)

我想出了办法,虽然可以,但是仍然有些笨拙...

显然,此想法是将侦听器附加到要链接的两个属性,并在每次更改另一个属性时更新一个属性。

需要花些时间才能将侦听器附加到内置axes对象的属性,您必须检索关联的meta.property。我将此封装在外部子函数findPropertyHandle中。

我使解决方案成为泛型,因此您可以将任何类型的属性链接在一起。现在,我没有对输入检查进行编程,因此,它当然只能在 compatible 属性上工作。 XLimYLim显然兼容,但是如果您尝试将XLimPlotBoxAspectRatioMode链接,则会在控制台中出现大量的红色和橙色文本。

%% Demo data and figure
x = linspace(0,24*pi,1000) ;
y = cos(x) ;
hf = figure ;
hax1 = subplot(1,2,1) ; hp1 = plot(x,y) ;
hax2 = subplot(1,2,2) ; hp2 = plot(y,x) ;

%% Find (meta)property handle
prop1 = findPropertyHandle( hax1 , 'XLim' ) ;
prop2 = findPropertyHandle( hax2 , 'YLim' ) ;

%% Add a listener to each property
% no callback yet because we need the reference of both listeners to be part of the callback arguments
lh1 = addlistener( hax1, prop1 , 'PostSet', @() [] ) ;
lh2 = addlistener( hax2, prop2 , 'PostSet', @() [] ) ;

%% group a few things for convenience
pl.obj2link   = [ hax1  ; hax2  ] ;     % axes handles
pl.props2link = { 'XLim' ; 'YLim' } ;   % name of properties to link
pl.listeners  = [ lh1 ; lh2 ] ;         % listener handle
pl.metaprops2link = [ prop1 ; prop2 ] ; % metaproperty handles

%% Set the callback of both listeners
% Have to use dot notation because the 'set' method is not defined for listener objects
lh1.Callback = @(h,e) LinkPropChangedFcn(h,e,pl) ;
lh2.Callback = @(h,e) LinkPropChangedFcn(h,e,pl) ;

Linked properties


LinkPropChangedFcn.m

的代码
function LinkPropChangedFcn( hobj, evt, plink )
%LinkPropChangedFcn Links 2 compatible properties

    % find which property was triggered
    changedPropIdx = find( hobj==plink.metaprops2link ) ;
    prop2changeIdx = 3-changedPropIdx ; % because cumsum([1 2])=3

    % disable the other listener to not trigger the property change on the
    % target object
    plink.listeners(prop2changeIdx).Enabled = false ;

    % retrieve property value
    val = get( plink.obj2link(changedPropIdx) , plink.props2link{changedPropIdx} ) ;

    % aplpy the value to the target object property
    set( plink.obj2link(prop2changeIdx) , plink.props2link{prop2changeIdx} , val ) ;

    % re-enable target listener
    plink.listeners(prop2changeIdx).Enabled = true ;

end

findPropertyHandle.m

的代码
function [ hprop ] = findPropertyHandle( hobj , propname )
%FINDPROPERTYHANDLE retrieve the handle of the meta.property object

    mco = metaclass(hobj) ;
    plist = mco.PropertyList;
    for k=1:numel(plist)
        if strcmpi(plist(k).Name,propname)
            fprintf('[%s] property was found at index #%d\n',propname,k)
            hprop = plist(k) ;
            return
        end
    end
    % no preperty was found if we are here
    hprop = [] ;
    fprintf('[%s] property was not found.\n',propname)

end

注意 我所说的笨拙是在使用“重置为原始视图”菜单而不是“缩小”时。该函数不会触发PostSet属性的XLim事件,因此更改并不总是传播到其他轴/属性。为了克服这个问题,在使用“重置为原始视图”之后,再次右键单击并“缩小”即可。这不会在单击的axes中进一步缩小(如果您已经在“原始视图”中),但是它将触发侦听器并更新第二个目标轴。

答案 1 :(得分:1)

是的,有可能。不要相信文档。我只是有同样的需要:我有一个曲面z(x,y):

x=-10:10; y=-15:15;
[xx,yy]=meshgrid(x,y);
z=real( exp( -(xx.^2/9+yy.^2/4+xx.*yy/12)) .* exp( 1i * (xx/4+yy/9-xx.*yy/12+1)));
xz= sum(z,1);
zy= sum(z,2);

并且想要绘制这样的表面和部分和

figure;
zyy= subplot(2,2,1); plot(zy,y);
xyz= subplot(2,2,2); contour(x,y,z);
xxz = subplot(2,2,4); plot(x,xz);

我要链接的是xyz和xxz的x轴以及zyy和xyz的y轴。

plot zyy xyz and xxz

linkaxes文档中所广告,这不起作用:

linkaxes([xyz xxz],'x');
linkaxes([xyz zyy],'y');

但是,至少在Matlab 2012b中,这种分解工作可以按预期进行:

set([xyz xxz],'XLimMode','manual');
set([xyz zyy],'YLimMode','manual');
hx=linkprop([xyz xxz],'XLim');
hy=linkprop([xyz zyy],'YLim');
setappdata(xxz,'graphics_linkaxes',hx);
setappdata(zyy,'graphics_linkaxes',hy);

如果查看链接轴的源代码,您会发现该代码正在尝试在链接的两端进行setappdata,这实际上是行不通的,但似乎不必要。

答案 2 :(得分:0)

不,使用linkaxeslinkplot无法做到这一点。

我担心你必须创建自己的系统,大致复制内部linkprop所做的事情,即在一个轴上监听事件,并通过相应的更改来回应它们到另一个。我害怕linkprop只允许你为每个人的同一财产做这件事。

答案 3 :(得分:0)

您可以使用技巧:使用linkaxes链接两个轴的'XLim'属性。在第二个轴中,而不是

plot(x2,y2)

你使用

plot(y2,x2)
view(90,-90)

这样,第二轴中的 x - 坐标包含 y 数据(感谢plot参数的反转),并且在< em> y 位置(感谢view的更改);和其他坐标类似。

因此,您基本上链接了两个'XLim'值,但让第二轴的 x - 坐标看起来就像是 y 坐标一样。< / p>

答案 4 :(得分:0)

这是我的解决方案,可在R2019a中使用 功能

function crosslinkaxes(ax,str)
%
% ax(1)=subplot(1,2,1);
% ax(2)=subplot(1,2,2);
% str='xy'; %link, x limits of ax(1) with ylimits of ax(2)
% crosslinkaxes(ax,str)

for k=1:numel(ax)
    propListener(k) = addlistener(ax(k),expand(str(k)),'PostSet',@event);
end

    function p=expand(str)
        switch str
            case 'x'
                p='XLim';
            case 'y'
                p='YLim';
            otherwise

                error(str)
        end
    end
    function event(src,evnt)
        %src.Name
        disp('lims')
        L=evnt.AffectedObject.(src.Name);
        for k=1:numel(ax)
            ax(k).(expand(str(k)))=L;

        end
        %      keyboard

    end
end