2008-11-07 22 views
5

Ist es möglich, eine GUI innerhalb einer Funktion zu schreiben?Wie erstellt man eine GUI in einer Funktion in MATLAB?

Das Problem ist, dass der Callback aller GUI-Funktionen im globalen Arbeitsbereich ausgewertet wird. Funktionen haben jedoch ihren eigenen Arbeitsbereich und können nicht auf Variablen im globalen Arbeitsbereich zugreifen. Ist es möglich, dass die GUI-Funktionen den Arbeitsbereich der Funktion nutzen? Zum Beispiel:

function myvar = myfunc() 
    myvar = true; 
    h_fig = figure; 

    % create a useless button 
    uicontrol(h_fig, 'style', 'pushbutton', ... 
         'string', 'clickme', ... 
         'callback', 'myvar = false'); 

    % wait for the button to be pressed 
    while myvar 
     pause(0.2); 
    end 

    close(h_fig); 

    disp('this will never be displayed'); 
end 

Diese Ereignis-Schleife wird auf unbestimmte Zeit laufen, da der Rückruf nicht myvar in der Funktion ändern wird. Stattdessen wird im globalen Arbeitsbereich eine neue myvar erstellt.

Antwort

5

fängt Es gibt eine Reihe von Möglichkeiten, build a GUI, wie die Verwendung des App Designer, GUIDE, oder erstellen Sie es programmgesteuert (ich werde diese Option unten veranschaulichen). Es ist auch wichtig, auf die different ways to define callback functions für Ihre GUI-Komponenten und die options available for sharing data between components zu achten.

Der Ansatz, den ich teilweise bin, verwendet nested functions als Rückrufe. Hier ist eine einfache GUI als Beispiel:

function make_useless_button() 

    % Initialize variables and graphics: 
    iCounter = 0; 
    hFigure = figure; 
    hButton = uicontrol('Style', 'pushbutton', 'Parent', hFigure, ... 
         'String', 'Blah', 'Callback', @increment); 

    % Nested callback function: 
    function increment(~, ~) 
    iCounter = iCounter+1; 
    disp(iCounter); 
    end 

end 

Wenn Sie diesen Code ausführen, angezeigt der Zähler um eins jedes Mal, wenn Sie die Taste drücken erhöhen sollte, da die verschachtelte Funktion increment Zugriff auf den Arbeitsbereich von make_useless_button hat und kann somit Ändern Sie iCounter. Beachten Sie, dass der Button Callback auf function handle bis increment gesetzt ist und dass diese Funktion standardmäßig zwei Argumente akzeptieren muss: ein Grafik-Handle für die UI-Komponente, die den Rückruf ausgelöst hat, und eine Struktur der zugehörigen Ereignisdaten. Wir ignore them with the ~ in diesem Fall, da wir sie nicht verwenden.

den oben beschriebenen Ansatz Ihr Problem erweitern, könnten Sie Ihre Schleife hinzufügen und den Rückruf ändern, so dass es Ihre Flagvariable auf false setzt:

function make_stop_button() 

    % Initialize variables and graphics: 
    keepLooping = true; 
    hFigure = figure; 
    hButton = uicontrol('Style', 'pushbutton', 'Parent', hFigure, ... 
         'String', 'Stop', 'Callback', @stop_fcn); 

    % Keep looping until the button is pressed: 
    while keepLooping, 
    drawnow; 
    end 

    % Delete the figure: 
    delete(hFigure); 

    % Nested callback function: 
    function stop_fcn(~, ~) 
    keepLooping = false; 
    end 

end 

Die drawnow hier benötigt wird, die Taste Rückruf eine Chance zu geben um den Programmablauf innerhalb der Schleife zu unterbrechen und den Wert keepLooping zu ändern.

1

Sie können eine Variable global in Ihrer Funktion und global im GUI-Code deklarieren, vor allem, wenn der Callback in einer separaten Funktion statt inline erfolgt. Ich habe dies in einer kleinen grafischen Benutzeroberfläche getan, die ich benutze, um ein schnelles Menüsystem zu erstellen.

In Ihrem Code über Sie in der Lage sein können, das globale Schlüsselwort auf Ihre Erstmeldung und auch auf Ihre Inline-Callback-d ‚global myvar = false‘

+0

OP muss die Ausgabevariable in etwas anderes ändern und "global myvar" im Basisarbeitsbereich erstellen, damit dies funktioniert. – Azim

+0

Ist das wirklich der einzige Weg? Es scheint ziemlich plump zu sein, globale Variablen für den Job zu verwenden. – bastibe

+0

Es ist der beste Weg, auf den ich gekommen bin - ich stimme zu, es ist ein bisschen hässlich, ich denke nicht, dass das Matlab-GUI-Modell sehr gut ist. Vielleicht möchten Sie den Code in dem nützlichen (?) Beitrag in Mathworks überprüfen. Die Website ist im Minutentakt. –

1

ich eine Lösung für das Problem hinzuzufügen gefunden. Die Callback-Funktion muss die Handle-Struktur der GUI ändern. Diese Struktur kann sowohl innerhalb des Callback aufgerufen werden und von der Funktion ohne neue Variablen auf den globalen Arbeitsbereich Einführung:

function myfunc() 
    h_fig = figure; 

    % add continue_loop to the GUI-handles structure 
    fig_handles = guihandles(h_fig); 
    fig_handles.continue_loop = true; 
    guidata(h_fig, fig_handles); 

    % create a useless button 
    uicontrol(h_fig, 'style', 'pushbutton', ... 
         'string', 'clickme', ... 
         'callback', @gui_callback); 

    % wait for the button to be pressed 
    while fig_handles.continue_loop 
     fig_handles = guidata(h_fig); % update handles 
     pause(0.2); 
    end 

    close(h_fig); 
    disp('callback ran successfully'); 
end 

% The arguments are the Matlab-defaults for GUI-callbacks. 
function gui_callback(hObject, eventdata, handles) 
    % modify and save handles-Structure 
    handles.continue_loop = false; 
    guidata(hObject, handles); 
end 

zur Kenntnis, dass seit der while-Schleife wird nur fig_handles aktualisieren, wenn es ausgeführt wird, haben Sie immer mindestens 0,2 Sekunden Verzögerung, bis die Schleife die Änderung von fig_handles.continue_loop

+0

Die Antwort, die Sie hier gegeben haben, sieht sicherlich korrekt aus, und so viele Leute behandeln wahrscheinlich diese Art von Problem. Es geht nur um die persönliche Präferenz: Manche Leute benutzen gerne GUIDE, während ich immer dachte, ich könnte die Dinge mit verschachtelten Funktionen sauberer machen (es ist allerdings ein bisschen mehr Arbeit). – gnovice

+0

Ich zweite das. Tatsächlich litt ich so sehr unter dem GUIDE-generierten Code, den ich fig2cmd schrieb - um aus einer .fig-Datei die Befehle zu extrahieren, die notwendig sind, um sie in einer m-Datei zu reproduzieren. –

Verwandte Themen