我正在尝试在matlab中创建一个简单的gui并遇到一些问题。这个简化程序的主要思想是我有一个滑块,它决定了正弦波的频率。两个图显示了结果信号。高分辨率为44100 Hz,低分辨率为100 Hz。另一个滑块确定绘制信号的长度(也以Hz为单位测量)。原始程序有更多的滑块可以添加更多的频率,但由于我认为它不重要,我试图将其缩小回来以解决这个问题。结果代码仍然非常大,对不起。
我的问题是它并不总是更新,我收到错误消息。我尝试将所有东西存放在手柄中,因为我认为这就是你应该如何做到的。 handles.lowresx包含低res时间标度,handles.highresx包含高res时间标度。然后在函数calcandplot(handles)中创建临时lowresy和highresy。每次移动时间间隔滑块时,都会从滑块移动回调中调用函数recalcx(hObject,newhz,handles),并计算新的lowresx和lowresy。它然后存储在guidata(hObject,handle)中(我希望),这些用于计算新的lowresy和highresy用于绘图。它似乎没有存储。
当它是回调函数中的嵌套函数时,我不确定如何保存数据。我应该在调用堆栈中一直调用guidata(hObject,handle),这意味着我必须将hObject作为参数传递给每个函数?或者只在最内在的功能?我已经尝试了两个,没有一个真的有用。如果我以后不需要它们,或者我是否应该将它们保存在句柄中,以使一切正常工作,那么仅仅计算lowresy和highresy并绘制它们就足够了吗?或者它是否足够了?
在调用set(handles.intervaltext,'String',num2str(val))之后是否必须调用guidata(句柄)或者是否自行更新?
我对手柄有疑问。我理解它的方式是每次调用函数时都会创建并传递一个副本。这是否会对您可以保存哪些大数据结构产生某种限制?如果在每个gui组件上调用某种事件时会创建一个副本(鼠标悬停,按下按键等),我当然可以看到事情会变得迟缓。有关如何处理此问题的任何提示?
错误讯息:
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))
答案 0 :(得分:1)
问题是在recalcx
内,您要通过添加字段handles
来修改lowresx
。您(正确地)使用guidata(hObject, handles)
将其保存到guidata。
问题是在调用函数(gui_OpeningFcn
)中,然后将修改后的不同的 handles
结构保存到guidata中handles
内的recalcx
结构不会传播回调用函数。
这个handles
结构没有那些字段然后在你的GUI周围传递并导致你看到的错误。
如何解决此问题的一个选择是让recalcx
返回修改后的handles
结构
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
然后调用函数可以有更新版本
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);