2008-11-07 14 views
5

¿Es posible escribir una GUI desde dentro de una función?¿Cómo crear una GUI dentro de una función en MATLAB?

El problema es que la devolución de llamada de todas las funciones de la GUI se evalúa en el espacio de trabajo global. Pero las funciones tienen su propio espacio de trabajo y no pueden acceder a las variables en el espacio de trabajo global. ¿Es posible hacer que las funciones de la GUI usen el espacio de trabajo de la función? Por ejemplo:

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 

Este evento de bucle se ejecutará de forma indefinida, ya que la devolución de llamada no modificará myvar en la función. En cambio, creará un nuevo myvar en el espacio de trabajo global.

Respuesta

5

Hay varias formas de build a GUI, como usar el Diseñador de aplicaciones, GUÍA o crearlo programáticamente (Ilustraré esta opción a continuación). También es importante conocer el different ways to define callback functions para los componentes de su GUI y el options available for sharing data between components.

El enfoque que me gusta es utilizar nested functions como devoluciones de llamada. Aquí hay una interfaz gráfica de usuario simple como un ejemplo:

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 

Cuando se ejecuta este código, el contador que aparece debería incrementarse en uno cada vez que se pulsa el botón, ya que la función anidada increment tiene acceso al espacio de trabajo de make_useless_button y por lo tanto puede modificar iCounter. Tenga en cuenta que la devolución de llamada del botón está configurada en function handle a increment, y que esta función debe aceptar dos argumentos de forma predeterminada: un controlador de gráficos para el componente UI que desencadenó la devolución de llamada y una estructura de datos de eventos asociados. Nos ignore them with the ~ en este caso, ya que no los estamos utilizando.

La ampliación del enfoque anterior a su problema particular, se puede inscribir su bucle y cambiar la devolución de llamada por lo que establece la variable de la bandera a falso:

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 

El drawnow se necesita aquí para darle al botón de devolución de llamada de la oportunidad para interrumpir el flujo del programa dentro del ciclo y modificar el valor de keepLooping.

1

Puede declarar una variable global en su función y global en el código GUI, ciertamente si la devolución de llamada está en una función separada en vez de en línea. He hecho esto en un pequeño GUI esqueleto que utilizo para hacer un sistema de menú rápido.

En el código anterior puede ser capaz de añadir la palabra clave global para su declaración inicial y también para su línea de devolución de llamada es decir, 'mivar mundial = false'

+0

OP tendrá que cambiar la variable de salida a otra cosa y crear "myvar global" en el espacio de trabajo base para que esto funcione. – Azim

+0

¿Es esta la única manera? Parece ser un poco contundente usar variales globales para el trabajo. – bastibe

+0

Es la mejor manera que he encontrado, estoy de acuerdo que es un poco feo, no creo que el modelo de Matlab GUI sea muy bueno. Es posible que desee comprobar el código en la contribución útil (?) En Mathworks. El sitio está caído en el minuto. –

1

he encontrado una solución al problema. La función de devolución de llamada tiene que modificar la estructura de manejo de la GUI. Esta estructura se puede acceder tanto desde el interior de la devolución de llamada y de la función sin introducir nuevas variables al espacio de trabajo mundial:

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 

nota que desde el bucle while sólo se actualizará fig_handles cuando se ejecuta, siempre tendrá al menos 0.2 segundos de retraso hasta que el lazo capte la modificación de fig_handles.continue_loop

+0

La respuesta que dio aquí ciertamente parece correcta, y esta es la cantidad de gente que probablemente maneje este tipo de problema. Se trata de preferencia personal: a algunas personas les gusta usar GUIDE, mientras que siempre sentí que podía hacer que las cosas se vean más limpias con funciones anidadas (aunque es un poco más trabajo). – gnovice

+0

Yo en segundo lugar. De hecho, sufrí tanto con el código generado por GUIDE, que escribí fig2cmd - para extraer de un archivo .fig los comandos necesarios para reproducirlo en un archivo m. –

Cuestiones relacionadas