Main Content

保存和加载图类的实例

ChartContainer 基类继承的图遵循与其他 MATLAB® 对象相同的保存和加载规则。但是,在某些情况下,您可能希望您的对象保存和加载其他信息。例如,为了支持保存和加载交互式更改(如旋转或缩放)的结果,必须将坐标区的修改视图存储在类的属性中。通过定义存储和检索这些类型的更改的属性和方法,用户可以保存和重新加载图的实例,同时保留其更改。

保存和加载坐标区更改的编码模式

内置坐标区交互会更改坐标区上的某些属性。例如,拖动以旋转三维图会更改 View 属性。同样,在图中滚动缩放会更改坐标区上的 XLimYLim 以及可能包含的 ZLim 属性。要在用户保存和重新加载图时保留更改,请将这些组件添加到您的类中:

  • 定义用于存储图状态的受保护属性 - 该属性提供当 MATLAB 保存图对象时用来存储坐标区更改的位置。例如,您可以将该属性命名为 ChartState

  • 定义用于检索图状态的 get 方法 - 根据 MATLAB 是保存还是加载图对象,该方法执行以下两项操作之一。当 MATLAB 保存图对象时,该方法会返回相关坐标区更改,以便保存它们。当 MATLAB 加载图对象时,该方法返回存储在 ChartState 属性中的坐标区更改。

  • 定义用于更新坐标区的受保护方法 - 当图对象加载到 MATLAB 中时,此方法对 ChartState 属性调用 get 方法,然后更新图的相关坐标区属性。

定义用于存储图状态的受保护属性

定义一个受保护属性来存储相关坐标区信息。此属性为空,除非 MATLAB 在保存过程中设置其值,或 MATLAB 加载图的已保存实例。用易于识别的有意义名称定义属性。例如,定义一个名为 ChartState 的属性。

properties (Access = protected)
    ChartState = []
end

定义检索图状态的 get 方法

ChartState 属性定义公共 get 方法。像所有 setget 方法一样,此方法自动继承 ChartState 属性的访问权限。MATLAB 在保存图实例时调用此方法。

在此方法中,创建一个名为 isLoadedStateAvailable 的变量,该变量存储一个 logical 值。当 ChartState 属性不为空时,该值为 true

接下来,编写一个条件语句来检查 isLoadedStateAvailable 的值。将语句分成下列子句:

  • if...then 子句 - isLoadedStateAvailable 值为 true。返回 ChartState 属性的内容。

  • else 子句 - isLoadedStateAvailable 值为 false。创建一个结构体并获取坐标区对象。仅当坐标区上的 XLimYLimZLim 属性发生变化时,才能将 XLimYLimZLim 字段添加到结构体中。要测试坐标区属性是否发生了更改,请检查对应的模式属性是否设置为 'manual'。由于没有与坐标区 View 属性相关联的模式属性,因此无需检查任何内容即可将 View 字段添加到结构体中。

methods
    function data = get.ChartState(obj)
        isLoadedStateAvailable = ~isempty(obj.ChartState);
            
         if isLoadedStateAvailable
             data = obj.ChartState;
         else
             data = struct;
             ax = getAxes(obj);
                
             % Get axis limits only if mode is manual.
             if strcmp(ax.XLimMode,'manual')
                 data.XLim = ax.XLim;
             end
             if strcmp(ax.YLimMode,'manual')
                 data.YLim = ax.YLim;
             end
             if strcmp(ax.ZLimMode,'manual')
                 data.ZLim = ax.ZLim;
             end
                
             % No ViewMode to check. Store the view anyway.
             data.View = ax.View;
         end
     end
end

定义更新坐标区的受保护方法

定义名为 loadstate 的受保护方法。在此方法中,执行以下步骤:

  • 查询 ChartState 属性,并将返回值存储为 data

  • 在更新坐标区上的对应属性之前,请检查是否存在 XLimYLimZLimView 字段。

  • 清除 ChartState 属性的内容。

创建此方法后,在 setup 方法的末尾(创建构成图的图形对象后)调用它。当 MATLAB 创建图的新实例或加载图实例时,将执行 setup 方法。

function loadstate(obj)
    data=obj.ChartState;
    ax = getAxes(obj);
            
    % Look for states that changed
    if isfield(data, 'XLim')
        ax.XLim=data.XLim;
    end
    if isfield(data, 'YLim')
        ax.YLim=data.YLim;
    end
    if isfield(data, 'ZLim')
        ax.ZLim=data.ZLim;
    end
    if isfield(data, 'View')
        ax.View=data.View;
    end
            
    % Reset ChartState to empty
    obj.ChartState=[];
end

示例:用于存储轴范围和视图的三维绘图

定义一个 MeshGradientChart 类,该类显示网格点处有 x 和 y 梯度向量的网格图。将此类设计为当用户保存和重新加载图实例时,坐标区的 XLimYLimZLimView 属性会被保留。

要定义此类,请在位于 MATLAB 路径上的文件夹中创建名为 MeshGradientChart.m 的程序文件。然后按照表中的步骤实现该类。

步骤实现

ChartContainer 基类派生而来。

classdef MeshGradientChart < matlab.graphics.chartcontainer.ChartContainer

定义公共属性。

    properties
        XData (:,:) double = []
        YData (:,:) double = []
        ZData (:,:) double = []
    end

定义私有属性。一个属性存储 Surface 对象,另一个属性存储 Quiver 对象。

    properties (Access = private,Transient,NonCopyable)
        SurfaceObject (1,1) matlab.graphics.chart.primitive.Surface
        QuiverObject (1,1) matlab.graphics.chart.primitive.Quiver
    end

定义一个受保护 ChartState 属性以存储坐标区状态。

    properties (Access = protected)
        ChartState = []
    end

实现 setup 方法。在本例中,调用 meshquiver3 函数以分别创建 SurfaceQuiver 对象。将对象存储在对应的属性中,并将坐标区的 hold 状态变为 'off'。然后调用 loadstate 方法以更新坐标区的状态。

    methods(Access = protected)
        function setup(obj)
            ax = getAxes(obj);
            
            % Create Mesh and Quiver objects.
            obj.SurfaceObject=mesh(ax,[],[],[],'FaceColor','none');
            hold(ax,'on')
            obj.QuiverObject=quiver3(ax,[],[],[],[],'Color','r','LineWidth',2);
            hold(ax,'off')
            
            % Load state of the axes.
            loadstate(obj);
        end

实现 update 方法。在本例中,更新网格图和梯度向量尾部的 x 和 y 坐标。然后更新向量的长度和方向。

        function update(obj)
            % Update Mesh data.
            obj.SurfaceObject.XData = obj.XData;
            obj.SurfaceObject.YData = obj.YData;
            obj.SurfaceObject.ZData = obj.ZData;
            
            % Update locations of vector tails.
            obj.QuiverObject.XData = obj.XData;
            obj.QuiverObject.YData = obj.YData;
            obj.QuiverObject.ZData = obj.ZData;
            
            % Update lengths and directions of vectors.
            [gradx,grady] = gradient(obj.ZData);
            obj.QuiverObject.UData = gradx;
            obj.QuiverObject.VData = grady;
            obj.QuiverObject.WData = zeros(size(obj.ZData));
        end

实现 loadstate 方法,该方法会更新坐标区并将 ChartState 属性重置为空数组。

        function loadstate(obj)
            data=obj.ChartState;
            ax = getAxes(obj);
            
            % Look for states that changed.
            if isfield(data, 'XLim')
                ax.XLim=data.XLim;
            end
            if isfield(data, 'YLim')
                ax.YLim=data.YLim;
            end
            if isfield(data, 'ZLim')
                ax.ZLim=data.ZLim;
            end
            if isfield(data, 'View')
                ax.View=data.View;
            end
            
            % Reset ChartState to empty.
            obj.ChartState=[];
        end
    end

实现 ChartState get 方法,该方法返回坐标区状态信息。

    methods
        function data = get.ChartState(obj)
            isLoadedStateAvailable = ~isempty(obj.ChartState);
            
            % Return ChartState content if loaded state is available.
            % Otherwise, return current axes state.
            if isLoadedStateAvailable
                data = obj.ChartState;
            else
                data = struct;
                ax = getAxes(obj);
                
                % Get axis limits only if mode is manual.
                if strcmp(ax.XLimMode,'manual')
                    data.XLim = ax.XLim;
                end
                if strcmp(ax.YLimMode,'manual')
                    data.YLim = ax.YLim;
                end
                if strcmp(ax.ZLimMode,'manual')
                    data.ZLim = ax.ZLim;
                end
                
                % No ViewMode to check. Store the view anyway.
                data.View = ax.View;
            end
        end
    end
end

接下来,创建图的一个实例。然后旋转或放大图并保存。当您将图加载回 MATLAB 时,该对象会保留交互式更改。

创建图的实例

[X,Y] = meshgrid(-5:5);
Z = X.^2 + Y.^2;
c = MeshGradientChart('XData',X,'YData',Y,'ZData',Z);

创建图时:

  • setup 方法会调用 loadstate 方法。

  • loadstate 方法会执行以下任务,这些任务最终对图对象或底层坐标区对象没有影响。

    • 调用 get.ChartState 方法,该方法返回包含坐标区 View 属性当前值的结构体。

    • 将坐标区上的 View 属性重置为存储在结构体中的值。

    • 清除 ChartState 属性的内容。

旋转或放大图并保存。

savefig(gcf,'mychart.fig')

保存图时,MATLAB 调用 get.ChartState 方法,该方法返回包含以下内容的结构体:

  • 坐标区上的 XLimYLimZLim 属性的值(仅当这些值发生了更改时)

  • 坐标区上的 View 属性的值

在 MATLAB 检索结构体后,会将该结构体存储在要保存的图对象的 ChartState 属性中。

加载保存的图。

openfig('mychart.fig')

加载图时:

  • setup 方法会调用 loadstate 方法。

  • loadstate 方法执行以下任务:

    • 调用 get.ChartState 方法,该方法从 ChartState 属性返回结构体。

    • 重置坐标区上的 XLimYLimZLimView 属性(仅当结构体包含对应的字段时)。

    • 清除 ChartState 属性的内容。

另请参阅

函数

属性

相关主题