【问题标题】:How can I access data from outside the app class in appdesigner (Matlab)如何从appdesigner(Matlab)中的应用程序类外部访问数据
【发布时间】:2019-01-17 04:04:09
【问题描述】:

我在 appdesigner (Matlab) 中创建了一个非常简单的 GUI,带有一个下拉菜单。此外,我获取了生成的代码(在“代码视图”选项卡下)并将其粘贴到一个普通的 .m 文件中(因为我想进一步向该代码添加更多内容)。我的问题是如何从这个自我生成的代码中访问某些变量,以便我可以在主类之外使用该值?

例如:

在 App 类中,对于这个下拉菜单部分,生成了以下代码行:

app.ColorDropDown = uidropdown(app.UIFigure);
app.ColorDropDown.Items = {'Red', 'Blue', 'Yellow'};
app.ColorDropDown.Position = [277 178 140 22];
app.ColorDropDown.Value = 'Red';

在这个应用程序类之外:根据在这个下拉菜单中选择的值,我想在一个普通变量中捕获它,并根据选择的颜色显示一些其他结果 p>

谢谢

【问题讨论】:

  • 您不应该使用 App Designer 在代码编辑器之外复制/粘贴代码。如果您想添加自己的代码,您应该使用 App Designer 中的“功能”按钮向您的类添加一个新功能。该应用程序还可以调用任何其他 matlab 函数,因此您可以通过在应用程序设计器代码中调用它来将信息从应用程序传递到另一个函数。
  • 很难给你一个好的答案,因为你不完全清楚你想要实现的用户体验是什么。一般来说 - 最好的方法是创建一个event listener。 “又快又脏”的方式是使用setappdata/getappdata。最后的手段是global 变量。
  • @Ajeya Gupta 不客气。
  • 目前尚不清楚您是在尝试监听更改还是只是将颜色放入基本工作区。如果是后者,那么您可以在下拉回调函数中使用assignin()。虽然我不会将它用于生产解决方案。

标签: matlab matlab-app-designer


【解决方案1】:

您的问题的本质似乎是关于在 GUI 之间共享数据,因为您声明要“根据所选颜色显示一些其他结果”。

注意:MATLAB documentation cautions: 请勿在您使用 App Designer 创建的应用中使用 UserData 属性

文档继续推荐sharing data among app designer appscreating multiwindow apps in app designer 的方法。

为了完整起见,我将提供一个与 MATLAB 文档不同的详细示例,说明如何完全在 App 设计器中完成此操作。

设置

我创建了 2 个应用程序设计器应用程序,controlGUI.mlappplotGUI.mlapp。运行 controlGUI() 一次加载两个 mlapp 文件,然后允许您通过 controlGUI 中的回调控制 plotGUI 的各个方面。当然,plotGUI 可以做任何事情,但我让它改变了绘制数据的视觉方面。

详情

为简单起见,我将 controlGUI 设置为主应用程序。我可以在 controlGUI 中添加一个名为PlotWindow 的属性,并让它包含调用plotGUI() 的输出;另一个mlapp。我还有一个回调函数,用于更新 plotGUI 中的 DATA 属性的三个下拉列表。此 DATA 属性附加了一个侦听器,该侦听器触发回调以更新 uiaxes 对象。

plotGUI

魔法真的在这个物体上。也就是说,我创建了一个名为 DATA 的属性并更改了访问权限。通过设置属性访问SetObservable = true,我们可以添加一个PostSet事件监听器,我在startupFcn期间存储在一个名为dataChangedListener的私有属性中。

properties (Access = public, SetObservable=true)
    DATA % A struct with xdata, ydata, fields. Other line prop fields ok
end

properties (Access = private)
    dataChangedListener % listener object for when DATA is changed.
end

然后启动函数startupFcn 使用一些(任意)数据初始化DATA 属性,因为结构然后 添加并启用PostSet 侦听器。

% Code that executes after component creation
    function startupFcn(app, data)
        if nargin < 2
            % create a default dataset
            data = struct();
            data.xdata = linspace(0,1,1001);
            data.ydata = sin(data.xdata.*2*pi*10);%10hz signal
            data.color = app.Axes.ColorOrder(1,:);
        end
        app.DATA = data;
        % plot the data
        line(data, 'parent', app.Axes);

        % add and enable PostSet event listener for the DATA property
        app.dataChangedListener = addlistener(...
            app,'DATA','PostSet', ...
            @(s,e) app.updatePlot ...
            );
        app.dataChangedListener.Enabled = true;
    end

PostSet 监听器调用方法app.updatePlot(),所以我们必须将此方法添加到我们的应用程序中。 每当app.DATA 中的任何内容被修改时,都会调用此方法。所以我创建了“函数”(正如代码浏览器所称的那样),它只是删除axes 子项(现有行)并使用line()低级 版本来绘制一个@ 987654325@ 基于app.DATA struct 对象:

function updatePlot(app)
        %clear plot
        delete(app.Axes.Children);
        % draw the new plot
        line(app.DATA, 'parent', app.Axes);
    end

是的,line() 将接受具有与有效行属性相对应的字段名称的结构,但我似乎无法具体找到参考。但是,如果您阅读了有关 inputParser object 的信息……抱歉,题外话了。

控制界面

这个对象比较简单。它将 plotGUI 保存在一个属性中,允许直接访问 plotGUI 属性和公共方法。

properties (Access = public)
    PlotWindow = plotGUI() % holds the reference to the plot window
end

我还在这里创建了一个updatePlot 回调方法,与 plotGUI 方法不同,我的命名不好。尽管如此,此控制方法从 controlGUI 下拉列表中获取值,然后修改 plotGUI DATA 结构,存储在 app.PlotWindow.DATA 中。因此,只要更改任何下拉菜单(ValueChangedFcn),就会调用这个回调。因此,DATA 结构的 PostSet 侦听器将触发回调以相应地更新绘图。

% Value changed function: LineColor, LineStyle, MarkerStyle
    function updatePlot(app, event)
        mStyle= app.MarkerStyle.Value;
        lStyle= app.LineStyle.Value;
        lColor = app.LineColor.Value;
        d = app.PlotWindow.DATA;
        switch mStyle
            case 'none'
                d.marker = 'none';
            case 'circle'
                d.marker = 'o';
            case 'diamond'
                d.marker = 'diamond';
            case 'point'
                d.marker = '.';
        end
        switch lStyle
            case 'none'                    
                d.linestyle = 'none';
            case 'solid'
                d.linestyle = '-';
            case 'dashed'
                d.linestyle = '--';
            case 'dotted'
                d.linestyle = ':';
        end
        d.color = lColor;
        % set the data back into the plotGUI
        % The plotGUI's DATA PostSet listener will update the actual plot
        app.PlotWindow.DATA = d;
    end

【讨论】:

    【解决方案2】:

    您不应该使用 App Designer 在代码编辑器之外复制/粘贴代码。如果您想添加自己的代码,您应该使用 App Designer 中的“功能”按钮向您的类添加一个新功能。该应用程序还可以调用任何其他 matlab 函数,因此您可以通过在应用程序设计器代码中调用它来将信息从应用程序传递到另一个函数

    例如,从我创建的演示中查看此示例。它使用下拉ChartTypeDropDown 来确定它应该绘制什么类型的图表。我添加了一个名为 DrawChart 的新 function,它使用来自 GUI 的数据根据​​在各个框中选择/输入的值绘制图表。

        function results = DrawChart(app)
            chartType = app.ChartTypeDropDown.Value;
            chartTime = app.TimeEditField.Value;
            chartA = app.AEditField.Value;
            chartB = app.BEditField.Value;
            chartC = app.CEditField.Value;
            t = [0:0.1:chartTime];
            if strcmp(chartType,'Sin')
                y = chartA * sin(chartB*t)+chartC;
            elseif strcmp(chartType,'Cos')
                y = chartA * cos(chartB*t)+chartC;
            elseif strcmp(chartType,'Exp')
                y = exp(t);
            else
                y = x;
            end
            ax = app.UIAxes;
            ax.Title.String = chartType;
            plot(ax,t,y);
        end
    

    该函数由链接到按钮的回调调用

        function DrawButtonPushed(app, event)
            DrawChart(app);
        end
    

    注意我如何调用常规的 matlab 函数,例如 sin/cos/exp。这些可以很容易地成为您编写的 Matlab 函数。

    【讨论】:

      猜你喜欢
      • 2010-12-28
      • 2013-05-25
      • 2015-12-02
      • 2010-10-29
      • 1970-01-01
      • 2021-11-29
      • 1970-01-01
      • 1970-01-01
      • 2017-04-30
      相关资源
      最近更新 更多