我在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';
此应用类的外部:根据我在此下拉菜单中选择的值,我想将其捕获为普通变量,并根据所选颜色显示其他结果>
谢谢
答案 0 :(得分:4)
似乎您的问题的实质是关于在GUI之间共享数据,因为您声明要“根据所选颜色显示其他结果”。
注意: MATLAB documentation cautions: 请勿在通过App Designer创建的应用中使用UserData
属性。
文档继续为sharing data among app designer apps和creating multiwindow apps in app designer推荐方法。
为了完整起见,我将提供一个与MATLAB文档不同的详细示例,说明如何在App Designer中完全完成此操作。
我创建了2个应用设计器应用,分别是 controlGUI.mlapp 和 plotGUI.mlapp 。运行controlGUI()
会一次加载两个mlapp文件,然后允许您从controlGUI的回调中控制plotGUI的各个方面。当然,plotGUI可以执行任何操作,但是我可以更改打印数据的外观。
为简单起见,我将controlGUI设置为主应用程序。我可以在controlGUI中添加一个名为PlotWindow
的属性,并使其包含调用plotGUI()
的输出;另一个mlapp。我还有一个回调函数,可用于三个下拉列表的回收,这些下拉列表用于更新plotGUI中的DATA属性。此DATA属性附加了一个侦听器,该侦听器将触发回调以更新uiaxes
对象。
魔术确实存在于此物体中。也就是说,我创建了一个名为DATA的属性并更改了访问权限。通过设置属性访问权限SetObservable = true
,我们可以添加一个PostSet
事件监听器,该监听器在dataChangedListener
期间存储在名为startupFcn
的私有属性中。
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
使用一些(任意)数据初始化struct属性,然后添加<{1}}侦听器。
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
的低级版本根据{{1}}结构对象绘制一个primitive line:
line()
是的,app.DATA
将接受一个结构,该结构的字段名称与有效的行属性相对应,但我似乎找不到专门的引用。但是,如果您读到有关inputParser object ...的问题,对不起,请离开话题。
此对象更简单。它将plotGUI保留在一个属性中,从而可以直接访问plotGUI属性和公共方法。
function updatePlot(app)
%clear plot
delete(app.Axes.Children);
% draw the new plot
line(app.DATA, 'parent', app.Axes);
end
我在这里还创建了一个line()
回调方法,与plotGUI方法不同,这对我来说是不好的命名。但是,此控制方法从controlGUI下拉列表中获取值,然后修改存储在properties (Access = public)
PlotWindow = plotGUI() % holds the reference to the plot window
end
中的plotGUI updatePlot
结构。因此,只要更改任何下拉列表(DATA
),就会调用此回调。因此,app.PlotWindow.DATA
结构的ValueChangedFcn
侦听器将触发回调以相应地更新绘图。
PostSet
答案 1 :(得分:1)
您不应该使用App Designer在代码编辑器之外复制/粘贴代码。如果要添加自己的代码,则应使用App Designer中的“函数”按钮将新函数添加到类中。该应用程序还可以调用其他任何matlab函数,因此您只需在应用程序设计器代码中调用它即可将信息从应用程序传递给另一个函数
例如,请参见我创建的演示中的示例。它使用下拉ChartTypeDropDown
来确定应绘制的图表类型。我添加了一个名为function
的新DrawChart
,它使用来自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函数一样容易。