【问题标题】:Match legend to axes objects将图例与坐标区对象匹配
【发布时间】:2014-02-14 12:27:40
【问题描述】:

上下文:

我有一个(程序化的)GUI,它在一些uipanel 育儿结构中包含几个axes 对象。其中一些 axes 关联了 legend 对象,有些则没有。
我想在我的 GUI 中包含一个按钮,它将当前可见的绘图复制到一个新图形中,包括它的 legend(如果有的话)。

我知道如何获取当前可见的uipanel 和其中所有axes 对象的句柄。我也知道如何区分axeslegends。

问题:

我如何匹配 legends 到 axes

例如,在一种情况下,我的 GUI 显示 2 axes 和一些绘图,每个绘图都有自己的 legend。当我单击“导出”按钮时,我想要创建 2 个新图形,每个包含一个 axes 及其对应的 legend
我目前能做的是

  1. 所有东西都放在一个图中(在这种情况下它们会重叠,因为它们在原始uipanels 中的位置是相同的),
  2. 每个轴和每个图例放入各自的图形中,
  3. 将所有轴放在一个中,将所有图例放在另一个图中,然后
  4. 所有坐标轴放在自己的图中,将所有图例放在同一个面板中。
  5. 按面板拆分,即将所有子图放到同一个图中,每组图放到自己的图中。

问题:

问题是,我没有这些对象的句柄。我只有uipanel 对象的句柄。面板内的图形是由另一个函数构建的,该函数包含各种棘手的东西,但不返回句柄。此外,所述面板的育儿结构使得使用 get(handles.panels{1},'Children') 之类的技巧很难做到这一点,因为它适用于某些情况,但并非所有情况。
我想过简单地导出面板(实际上有一个可以执行此操作的工作版本),但这有几个问题,主要与图形工具和调整大小有关。当我使用“导出”按钮时,我想摆脱面板。

代码片段/示例:

以下代码 sn-p 将创建一个示例 GUI,它可以访问我在完整 GUI 中可以访问的所有句柄。单击按钮将显示我要“工作”的不同版本。我想要的是每个轴的一个图包括它的图例,如果它有的话。第 4 版(相同的父版)接近,但如果遇到subplots 则会中断,第 5 版(按面板)只是将整个子图组放入一个窗口(在这种情况下,至少它们不会重叠)。将代码复制到一个新的.m文件中试试看。

function test
    figure(1)
    clf
    t=(0:0.1:10)'; %'// dummy comment
    p2 = uipanel('Visible','off','Position',[0 0 1 1]);
    p1 = uipanel('position',[0 0 1 1]);
    p11 = uipanel('Parent',p1,'Position',[0 0 0.5 0.9]);
    p12 = uipanel('Parent',p1,'Position',[0.5 0 0.5 0.9]);
    uicontrol('Style','push','String','all in one','Units','norm',...
        'Position',[0.05 0.91 0.14 0.06],'Callback',@export1);
    uicontrol('Style','push','String','all in own','Units','norm',...
        'Position',[0.24 0.91 0.14 0.06],'Callback',@export2);
    uicontrol('Style','push','String','by type','Units','norm',...
        'Position',[0.43 0.91 0.14 0.06],'Callback',@export3);
    uicontrol('Style','push','String','same parent','Units','norm',...
        'Position',[0.62 0.91 0.14 0.06],'Callback',@export4);
    uicontrol('Style','push','String','same panel','Units','norm',...
        'Position',[0.81 0.91 0.14 0.06],'Callback',@export5);
    subplot(1,1,1,'Parent',p11)
    plot(t,[sin(t) cos(t)])
    legend('Sine','Cosine')
    subplot(2,1,1,'Parent',p12)
    plot(t,[polyval([0.05 -1 2],t) exp(-t) abs(t-3)])
    subplot(2,1,2,'Parent',p12)
    plot(t,erf(t))
    legend('Error function')

    function export1(~,~)
        current = findobj('Type','uipanel','Parent',1,'Visible','on');
        visible_axes = findobj(current,'Type','axes');
        copyobj(visible_axes,figure);
    end

    function export2(~,~)
        current = findobj('Type','uipanel','Parent',1,'Visible','on');
        visible_axes = findobj(current,'Type','axes');
        for i=1:length(visible_axes)
            copyobj(visible_axes(i),figure);
        end
    end

    function export3(~,~)
        current = findobj('Type','uipanel','Parent',1,'Visible','on');
        visible_axes = findobj(current,'Type','axes','Tag','');
        visible_legends = findobj(current,'Tag','legend');
        copyobj(visible_axes,figure);
        copyobj(visible_legends,figure);
    end

    function export4(~,~)
        current = findobj('Type','uipanel','Parent',1,'Visible','on');
        visible_axes = findobj(current,'Type','axes','Tag','');
        visible_legends = findobj(current,'Tag','legend');
        for i=1:length(visible_axes)
            par = get(visible_axes(i),'Parent');
            same = findobj(visible_legends,'Parent',par);
            h=figure;
            copyobj(visible_axes(i),h)
            copyobj(same,h)
        end
    end

    function export5(~,~)
        current = findobj('Type','uipanel','Parent',1,'Visible','on');
        visible_axes = findobj(current,'Type','axes');
        parents = cell2mat(get(visible_axes,'Parent'));
        uparents = unique(parents);
        for i=1:length(uparents)
            copyobj(visible_axes(parents==uparents(i)),figure)
        end
    end
end

【问题讨论】:

    标签: matlab legend axes


    【解决方案1】:

    在图中,图形对象按层次组织,都可以单独处理。例如,axes 是图形的子节点,plot 是轴的子节点,图例构建为轴。

    以下示例绘制 2 条线(红色和蓝色,带有图例),然后使用 copyobj 混合图和图例。

    figure;
    subplot(1,2,1)
    hp1 = plot(1:10,'r')
    hl1 = legend('red')
    
    subplot(1,2,2)
    hp2 = plot(1:10,'b')
    hl2 = legend('blue')
    
    hf = figure;
    hax = axes;
    copyobj(hp1, hax);    %copy plot to axes
    copyobj(hl2, hf);     %copy legend to figure
    

    虽然没有使用 GUI 测试。

    【讨论】:

    • 问题是,我无权访问hl1hl2,如您的示例所示。因此,我试图稍后检索它们。想象一下您的第一个图形(带有子图)被保存为.fig 并在另一个函数/脚本/会话中重新打开。那你就没有把手了。在这种情况下,您将如何实现相同的目标(或实际复制匹配的目标,但循环相同)?
    • 保存图形会保存所有子轴,包括图例。我不明白为什么情节/传说在你的场景中是分离的。此外,您始终可以通过简单地调用legend 来重新创建基于图形的图例。最后,您可以使用set(gcf, 'UserData', legend_handle)将图例数据嵌入到图中以供稍后检索。
    • 它们没有分离,我想分离它们。我想打开包含您的子图图形的.fig,然后创建一个仅包含红色轴及其图例的新图形。我无法将图例句柄保存在 UserData 中,因为我一开始就没有得到它。图形是由我无法更改的外部函数创建并加载到uipanel 对象中的。该函数不会返回图例句柄。
    【解决方案2】:

    我认为更简单的解决方案是将要保存的图形的轴保存为 fig 文件。

    h = figure(1);
    
    x = linspace(1,100);
    y = 2*x;
    
    ax = findall(h,'type','axes');
    plot(x,y);
    
    save('youraxes', 'ax');
    hgsave(h, 'yourfig.fig');
    

    我正在使用 Matlab R2012a,或者在 R2013a 或 b 中,保存无花果的功能现在是 savefig

    【讨论】:

    • 这对解决问题有何帮助?如果您指的是我对 Macduff 的回答的评论,那只是澄清我想要做什么的一个例子。这与我的实际问题无关。
    【解决方案3】:

    获得坐标区句柄后,您可以使用

    找到相应的图例句柄

    legend_handle = legend(axes_handle)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-16
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      相关资源
      最近更新 更多