在GUIDE,Matlab中的嵌套函数中存储数据 [英] Storing data in nested functions in GUIDE, Matlab

查看:94
本文介绍了在GUIDE,Matlab中的嵌套函数中存储数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在matlab中创建一个简单的gui并遇到一些问题.这个简化程序的主要思想是我有一个滑块,它确定正弦波的频率.两幅图显示了得到的信号.高解析度为44100 Hz,低解析度为100 Hz.另一个滑块确定要绘制的信号的长度(也以Hz为单位).原始程序具有更多的滑块以添加更多的频率,但是由于我认为这并不重要,因此我尝试将其缩小以解决此问题.结果代码仍然很大,对此感到抱歉.

I'm trying to create a simple gui in matlab and have some problems. The main idea of this simplified program is that I have a slider, it determines the frequency of a sine wave. Two plots show the resulting signal. A high res in 44100 Hz, and a low res in 100 Hz. Another slider determines the length of the signal being plotted (also this measured in Hz). The original program has quite a few more sliders to add more frequencies, but since I didn't think it was important I tried to scale it back for this question. The resulting code is still quite large, sorry for that.

我的问题是,它并不总是更新,并且收到错误消息.我尝试将所有内容存储在句柄中,因为我认为这是您应该执行的操作. handles.lowresx包含低分辨率时间刻度,handles.highresx包含高分辨率时间刻度.然后在函数calcandplot(handles)中创建临时的低分辨率和高分辨率.每次移动时间间隔滑块时,都会从滑块移动回调中调用函数recalcx(hObject,newhz,handles),并计算新的lowresx和lowresy.然后将其存储在guidata(hObject,handles)中(我希望如此),这些用于计算新的低分辨率和高分辨率进行绘图.它似乎没有被存储.

My problem is it doesn't always update, and I get error messages. I try to store everything in handles, since I think this is how you're supposed to do it. handles.lowresx contains the low res time scale, handles.highresx contains the high res time scale. A temporary lowresy and highresy is then created in the function calcandplot(handles). Every time the time interval slider is moved, the function recalcx(hObject, newhz, handles) is called from the slider movement callback and a new lowresx and lowresy is calculated. It is then stored in guidata(hObject,handles) (I would hope) and these are used to calculate new lowresy and highresy for plotting. It doesn't seem to be stored though.

当它是回调函数中的嵌套函数时,我现在不确定如何保存数据.我是否应该在调用堆栈中一直向上调用guidata(hObject,handles),这意味着我必须将hObject传递为每个函数的参数?还是仅在最内部的功能上?我都尝试过,但都没有真正起作用.如果以后不需要它们,仅计算低分辨率和高分辨率并绘制它们就足够了,还是应该将它们保存在句柄中以使所有功能正常工作?

I'm not sure how to save the data now when it is a nested function inside the callback function. Am I supposed to call guidata(hObject, handles) all the way up in the call stack, meaning I have to pass down hObject as an argument to every function? Or only in the most inner function? I've tried both and none really work. And is it enough to just calculate lowresy and highresy and plot them, if I don't need them later, or should I save them in handles too, to make everything work right?

我是否必须在调用set(handles.intervaltext,'String',num2str(val))之后调用guidata(handles)还是自行更新?

Do I have to call guidata(handles) after calling set(handles.intervaltext, 'String', num2str(val)) or does it update itself?

我对手柄有疑问.据我了解,每次调用一个函数时,都会创建并传递一个副本.这是否对您可以保存在那里的大数据结构带来某种限制?如果在调用某种事件(鼠标悬停,按键等)时为每个gui组件创建了一个副本,那么我当然可以看到事情会变得迟钝.有关如何处理此问题的任何提示?

And I have a question about handles. The way I understand it a copy is created and passed down every time a function is called. Does this pose some kind of restrictions on how big data structures you can save there for it to be efficient? If a copy is created for every gui component when some kind of event is called on it (mouseover, key pressed etc) I can certainly see how things can get sluggish. Any tips for how to handle this?

错误消息:

Reference to non-existent field 'lowresx'.

Error in gui>calcandplot (line 85)
lowresy = wave(handles.lowresx, handles.freq1);

Error in gui>intervalslider_Callback (line 106)
calcandplot(handles);

代码:

function varargout = gui(varargin)
% GUI MATLAB code for gui.fig
%      GUI, by itself, creates a new GUI or raises the existing
%      singleton*.
%
%      H = GUI returns the handle to a new GUI or the handle to
%      the existing singleton*.
%
%      GUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in GUI.M with the given input arguments.
%
%      GUI('Property','Value',...) creates a new GUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before gui_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to gui_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help gui

% Last Modified by GUIDE v2.5 12-Oct-2016 14:18:38

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @gui_OpeningFcn, ...
                   'gui_OutputFcn',  @gui_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before gui is made visible.
function gui_OpeningFcn(hObject, eventdata, handles, varargin)
handles.freq1 = 0;
handles.lowsr = 1000;
handles.sr = 44100;
handles.lenhz = 220;
recalcx(hObject, handles.lenhz, handles);
'recalculated'

% Choose default command line output for gui
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes gui wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = gui_OutputFcn(hObject, eventdata, handles) 
varargout{1} = handles.output;

% --- Executes on slider movement.
function slider1_Callback(hObject, eventdata, handles)
val = get(hObject,'Value');
handles.freq1 = val;
guidata(hObject, handles);
set(handles.text1, 'String', num2str(val));
calcandplot(handles);

% --- Executes during object creation, after setting all properties.
function slider1_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end

function calcandplot(handles)
lowresy = wave(handles.lowresx, handles.freq1);
highresy = wave(handles.highresx, handles.freq1);
axes(handles.axes1);
plot(handles.lowresx,lowresy, 'o');
axes(handles.axes2);
plot(handles.highresx,highresy, 'o');

function y = wave(x, freq1)
% x in sec
y = sin(x*freq1);

% --- Executes on slider movement.
function intervalslider_Callback(hObject, eventdata, handles)
val = get(hObject,'Value');
recalcx(hObject, val, handles);

strcat('val is now ', num2str(val))
strcat('handles.lenhz is now', num2str(handles.lenhz))
guidata(hObject, handles);
set(handles.intervaltext, 'String', num2str(val));
handles
calcandplot(handles);

% --- Executes during object creation, after setting all properties.
function intervalslider_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end

function recalcx(hObject, newhz, handles)
handles.lenhz = newhz;
handles.lowresx = (0:1/handles.lowsr:(2*pi)/handles.lenhz)';
handles.highresx = (0:1/handles.sr:(2*pi)/handles.lenhz)';
strcat('inside handles is', num2str(handles.lenhz))
guidata(hObject, handles);
strcat('inside handles again is', num2str(handles.lenhz))

推荐答案

问题在于,在recalcx中,您正在通过添加字段lowresx来修改handles.您(正确)使用guidata(hObject, handles)将其保存到guidata.

The issue is that within recalcx, you are modifying handles by adding the field lowresx. You (correctly) save this to the guidata using guidata(hObject, handles).

问题在于,在调用函数(gui_OpeningFcn)中,您随后保存了一个不同 handles结构,该结构在guidata中没有这些字段,因为对recalcx中的>结构不会传播回调用函数.

The issue is that in the calling function (gui_OpeningFcn), you then save a different handles struct that doesn't have those fields to the guidata since the modifications to the handles structure within recalcx aren't propagated back to the calling function.

handles结构中没有这些字段,然后将它们传递到GUI周围并导致您看到错误.

It is this handles struct without those fields that is then passed around your GUI and causes the error you're seeing.

解决此问题的一种方法是让recalcx返回修改后的handles结构

One option for how to fix this would be to have recalcx return the modified handles struct

function handles = recalcx(hObject, newhz, handles)
    handles.lenhz = newhz;
    handles.lowresx = (0:1/handles.lowsr:(2*pi)/handles.lenhz)';
    handles.highresx = (0:1/handles.sr:(2*pi)/handles.lenhz)';
    strcat('inside handles is', num2str(handles.lenhz))
    guidata(hObject, handles);
    strcat('inside handles again is', num2str(handles.lenhz))
end

然后调用函数可以具有更新的版本

And then the calling function can have an updated version

function gui_OpeningFcn(hObject, eventdata, handles, varargin)
    handles.freq1 = 0;
    handles.lowsr = 1000;
    handles.sr = 44100;
    handles.lenhz = 220;
    handles = recalcx(hObject, handles.lenhz, handles);

    % Choose default command line output for gui
    handles.output = hObject;

    % Update handles structure
    guidata(hObject, handles);

这篇关于在GUIDE,Matlab中的嵌套函数中存储数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆