首页 > 解决方案 > Behaviour of axis properties with 'yyaxis'

问题描述

Create a figure with two y-axes, using yyaxis:

figure
yyaxis left
hl = plot([0 10],[0 10],'-');
yyaxis right
hr = plot([0 10],[10 0],'--');

The following curious behaviour has been found. This has been tested in R2017b and in R2019a on Windows 10.

The objects hl and hr seem to belong to the same axis (that is, yyaxis does not create a new axis):

>> get(hr, 'parent')==get(hl, 'parent')
ans =
  logical
   1

However, the 'children' property of the axis only reflects one object:

>> get(get(get(hl, 'parent'), 'children'), 'LineStyle')
ans =
    '--'
>> get(get(get(hr, 'parent'), 'children'), 'LineStyle')
ans =
    '--'

Also, the YAxisLocation' property of the parent axis has the same value for both objects:

>> get(get(hl, 'parent'), 'YAxisLocation')
ans =
    'right'
>> get(get(hr, 'parent'), 'YAxisLocation')
ans =
    'right'

If we now click on the solid line, to make it the current object,

>> get(get(get(gco, 'parent'), 'children'), 'LineStyle')
ans =
    '-'
>> get(get(get(hl, 'parent'), 'children'), 'LineStyle')
ans =
    '-'
>> get(get(get(hr, 'parent'), 'children'), 'LineStyle')
ans =
    '-'
>> get(get(gco, 'parent'), 'YAxisLocation')
ans =
    'left'

Similarly, if we now click on the dotted line,

>> get(get(get(gco, 'parent'), 'children'), 'LineStyle')
ans =
    '--'
>> get(get(get(hl, 'parent'), 'children'), 'LineStyle')
ans =
    '--'
>> get(get(get(hr, 'parent'), 'children'), 'LineStyle')
ans =
    '--'
>> get(get(gco, 'parent'), 'YAxisLocation')
ans =
    'right'

As a check,

>> get(gcf, 'children')

gives only one axis too, and

>> get(get(gcf, 'children'), 'children')

behaves similarly: only the object that was plotted last, or thas has been made current, is listed.

The above behaviour can be summarized as follows:

It's not clear how to make sense of this behaviour. The following questions naturally arise:

标签: matlabgraphicsmatlab-figure

解决方案


To me it looks like yyaxis does some nasty-behind-the-scenes things and there's lots of hidden data we can't access.

The documentation does say that:

yyaxis left activates the side of the current axes associated with the left y-axis. Subsequent graphics commands target the left side.

and

The Children property of the Axes object only contains the children for the active side. To access all the children for both sides, use the allchild function.

Changing the "side" with yyaxis therefore changes the contents of the Axes object, I presume that the contents for the other side gets stored in some hidden location that I haven't been able to find. yyaxis is P-code, so we won't be able to figure out what exactly it is doing.

This is interesting:

figure
yyaxis left
hl = plot([0 10],[0 1],'-');
yyaxis right
hr = plot([0 10],[100 0],'--');

h = gca;

yyaxis left
h.YLim

yyaxis right
h.YLim

The code creates left and right axes with different limits. We get the handle to the axes, change to left, read the limits from the handle, then change to right and read the same property again. The first time it returns [0,1], the second time it is [0,100]. That is, the Axes object with handle h changes when we call yyaxis.

The only indication I've found that h points to axes with two sides is that h.YAxis returns two handles to NumericRuler objects, one for each side.


I can't but feel this is awkward behavior. I would have expected there to be two Axes objects, both with the same Position property, and maybe with listeners that keep the two in sync.


推荐阅读