2016-10-12 1 views
0

私は簡単なGUIをmatlabに作成しようとしていて、いくつか問題があります。この単純化されたプログラムの主なアイデアは、私はスライダを持っており、正弦波の周波数を決定するということです。 2つのプロットが、結果として生じる信号を示す。 44100 Hzで高解像度、100 Hzで低解像度。もう1つのスライダは、プロットされる信号の長さを決定します(これもHz単位で測定されます)。元のプログラムには、より多くの周波数を追加するスライダがかなりありますが、重要ではないと思ったので、私はこの質問のために元に戻そうとしました。結果のコードはまだかなり大きいです。残念です。GUIDE、Matlabの入れ子関数にデータを保存

私の問題は、常に更新されるとは限らず、エラーメッセージが表示されることです。私はハンドルの中にすべてを格納しようとします、なぜなら、これはあなたがそれをやるべきだと思うからです。 handles.lowresxには低分解能の時間スケールが含まれ、handles.highresxには高分解能の時間スケールが含まれます。関数calcandplot(ハンドル)に、一時的な怠惰と高級感が作成されます。時間間隔スライダが移動されるたびに、関数recalcx(hObject、newhz、handles)がスライダ移動コールバックから呼び出され、新しいlowresxとlowresyが計算されます。それはguidata(hObject、handles)に保存されます(私が望むでしょう)。これらはプロットのために新しい怠け者と高尚なものを計算するために使われます。しかし、それは格納されていないようです。

コールバック関数内でネストされた関数であるときにデータを保存する方法がわかりません。コールスタックでguidata(hObject、handles)を呼び出す必要があります。つまり、すべての関数の引数として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)) 

答えて

1

問題は、フィールドlowresxを追加することにより、recalcx以内に、あなたはhandlesを変更しているということです。あなたは(正確に)guidata(hObject, handles)を使ってこれをguidataに保存します。

問題は、呼び出し元の関数(gui_OpeningFcn)で、あなたはrecalcxhandles構造への変更がバックに反映されませんので、関数guidataにそれらのフィールドを持っていない異なるhandles構造体を保存することです呼び出し関数

これはhandlesのフィールドで、GUIの周りを通過し、表示されているエラーが発生します。この問題を解決する方法については

1つのオプションは、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); 
+0

感謝を持つことができることであろう。そのようなものになると思った。私はこれを複数のソースから読み上げようとしましたが、実際に私の頭をまっすぐにすることはできません。 なぜguidata(hObject、handles)を使用してrecalcx関数でそれを更新し、gui_OpeningFcnで無効にするだけでは不十分ですか? gui_OpeningFcnでそれ以上の変更を加えないと仮定すると、それは保存されませんか?私はあなたがハンドルを上書きしてはならない場所を読んで、その中のフィールドだけを変更するので、recalcx関数の値として渡すことを恐れていたのです。 – user1661303

+1

@ user1661303 'recalcx'関数の' handles'構造体に加えられた変更は、呼び出し元関数の 'handles'変数には存在しません。 'guidata'を' recalcx'を呼び出した後に呼び出し関数*に保存するので、それは "良い" 'handles'構造体を上書きします。 – Suever

関連する問題