2016-10-12 4 views
0

Ich versuche, eine einfache GUI in Matlab zu erstellen und einige Probleme haben. Die Grundidee dieses vereinfachten Programms ist, dass ich einen Schieberegler habe, der die Frequenz einer Sinuswelle bestimmt. Zwei Plots zeigen das resultierende Signal. Eine hohe Auflösung in 44100 Hz und eine niedrige Auflösung in 100 Hz. Ein anderer Schieberegler bestimmt die Länge des geplotteten Signals (ebenfalls in Hz). Das ursprüngliche Programm hat noch ein paar Schieberegler, um mehr Frequenzen hinzuzufügen, aber da ich es nicht für wichtig hielt, habe ich versucht, es für diese Frage zu skalieren. Der resultierende Code ist immer noch ziemlich groß, sorry dafür.Speichern von Daten in geschachtelten Funktionen in GUIDE, Matlab

Mein Problem ist, es wird nicht immer aktualisiert, und ich bekomme Fehlermeldungen. Ich versuche, alles in Griffen zu speichern, da ich denke, so soll es gemacht werden. handles.logresx enthält die Zeitskala mit niedriger Auflösung, handles.highresx enthält die Zeitskala mit hoher Auflösung. In der Funktion calcandplot (handles) wird dann ein temporäres lowresy und ein highresy erzeugt. Jedes Mal, wenn der Schieberegler des Zeitintervalls verschoben wird, wird die Funktion recalcx (hObject, newhz, handles) vom Slider-Bewegungsrückruf aufgerufen und ein neues lowresx und lowresy berechnet. Es wird dann in Guidata (hObject, handles) gespeichert (ich hoffe) und diese werden verwendet, um neue lowresy und highresy für das Plotten zu berechnen. Es scheint jedoch nicht gespeichert zu sein.

Ich bin nicht sicher, wie Sie die Daten jetzt speichern, wenn es eine geschachtelte Funktion innerhalb der Callback-Funktion ist. Soll ich Guidata (hObject, Handles) den ganzen Weg im Callstack aufrufen, was bedeutet, dass ich hObject als Argument an jede Funktion übergeben muss? Oder nur in der innersten Funktion? Ich habe beides versucht und keiner funktioniert wirklich. Und ist es genug, um nur geringe und hohe Werte zu berechnen und sie zu plotten, wenn ich sie später nicht brauche, oder sollte ich sie auch in Griffen speichern, damit alles richtig funktioniert?

Muss ich guidata (handles) nach Aufruf von set aufrufen (handles.intervaltext, 'String', num2str (val)) oder aktualisiert es sich selbst?

Und ich habe eine Frage über Griffe. So wie ich es verstehe, wird bei jedem Aufruf einer Funktion eine Kopie erstellt und übergeben. Stellt dies eine Art Beschränkung dar, wie große Datenstrukturen dort gespeichert werden können, um effizient zu sein? Wenn eine Kopie für jede GUI-Komponente erstellt wird, wenn irgendeine Art von Ereignis aufgerufen wird (Mouseover, Taste gedrückt usw.), kann ich sicherlich sehen, wie die Dinge träge werden können. Irgendwelche Tipps für den Umgang damit?

Fehlermeldung:

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); 

Code:

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)) 

Antwort

1

Das Problem ist, dass recalcx innerhalb Sie handles durch modifizieren das Feld lowresx hinzufügen. Sie speichern dies (korrekt) in der Guidata mit guidata(hObject, handles).

Das Problem ist, dass in der aufrufenden Funktion (gui_OpeningFcn), können Sie dann eine verschiedenehandles Struktur speichern, die innerhalb recalcx nicht diese Felder auf die guidata, da die Änderungen an der handles Struktur haben, werden nicht zurück zu propagierte die aufrufende Funktion.

Es ist diese handles Struktur ohne diese Felder, die dann um Ihre GUI weitergegeben wird und den Fehler verursacht, den Sie sehen.

Eine Möglichkeit, wie dies zu beheben wäre, zu haben recalcx Rückkehr des modifizierten 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 

Und dann kann die anrufende Funktion haben eine aktualisierte 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); 
+0

Dank. Dachte, es wäre so etwas. Ich habe versucht, dies aus mehreren Quellen zu lesen, aber ich kann meinen Kopf nicht richtig verstehen. Warum ist es nicht genug, es nur in recalcx Funktion mit Guidata (hObject, Handles) zu aktualisieren und deaktivieren Sie es in gui_OpeningFcn? Würde es dann nicht gespeichert werden, wenn ich davon ausgehe, dass ich in gui_OpeningFcn keine weiteren Änderungen daran mache? Ich habe irgendwo gelesen, dass man Griffe niemals überschreiben darf, nur Felder darin ändern, also habe ich wohl Angst gehabt, es als Wert in der recalcx-Funktion zu übergeben. – user1661303

+1

@ user1661303 Änderungen an der 'handles'-Struktur in' recalcx'-Funktion sind in der 'handles' -Variablen der aufrufenden Funktion nicht vorhanden. Da Sie die 'guidata' in der aufrufenden Funktion * nach dem Aufruf von' recalcx' speichern, wird die "good" 'handles' Struktur überschrieben. – Suever

Verwandte Themen