我正試圖在matlab中創建一個簡單的gui,並且有一些問題。這個簡化程序的主要思想是我有一個滑塊,它決定了正弦波的頻率。兩張圖顯示了結果信號。 44100 Hz的高分辨率,100 Hz的低分辨率。另一個滑塊決定了繪製信號的長度(也以Hz爲單位)。原來的程序有更多的滑塊添加更多的頻率,但由於我不認爲這很重要,我試圖縮小這個問題。由此產生的代碼仍然很大,對此感到遺憾。在GUIDE,Matlab中存儲嵌套函數中的數據
我的問題是它並不總是更新,我收到錯誤消息。我試圖把所有東西都存儲在句柄中,因爲我認爲這就是你應該這樣做的方式。 handles.lowresx包含低分辨率時間比例,handles.highresx包含高分辨率時間比例。然後在函數calcandplot(句柄)中創建一個臨時的低結點和高結點。每次移動時間間隔滑塊時,函數recalcx(hObject,newhz,handles)都將從滑塊移動回調中調用,並計算新的低方向和低方向。然後存儲在guidata(hObject,句柄)(我希望),這些用於計算繪圖的新低邊和高邊。它似乎並沒有被儲存。
我不確定當它是回調函數內部的嵌套函數時,現在如何保存數據。我是否應該在調用堆棧中一直調用guidata(hObject,句柄),這意味着我必須將hObject作爲參數傳遞給每個函數?還是隻在最內在的功能?我已經嘗試過但沒有一個真正的工作。如果我以後不需要它們,或者我是否應該將它們也保存在句柄中,以便使所有的工作都正確,那麼僅僅計算低風險和高風險並繪製它們就足夠了嗎?
是否必須在調用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))
感謝。認爲它會是這樣的。我試着從多個來源讀到這一點,但不能真正讓我的頭腦清楚。 爲什麼僅僅用guidata(hObject,handles)在recalcx函數中更新它並且在gui_OpeningFcn中禁用它就足夠了?假設我沒有在gui_OpeningFcn中做任何更改,它會不會被保存呢?我讀過一個你永遠不應該覆蓋句柄的地方,只能改變它的字段,所以我想這就是爲什麼我害怕將它作爲recalcx函數中的一個值傳遞的原因。 – user1661303
@ user1661303對'recalcx'函數中'handles'結構所做的任何更改都不存在於調用函數的'handles'變量中。由於您在調用recalcx之後將'guidata'保存在調用函數*中,它將覆蓋「good」'handles'結構。 – Suever