2008-11-07 2 views
5

Возможно ли написать графический интерфейс изнутри функции?Как создать графический интерфейс внутри функции в MATLAB?

Проблема в том, что обратный вызов всех GUI-функций оценивается в глобальной рабочей области. Но функции имеют собственное рабочее пространство и не могут обращаться к переменным в глобальной рабочей области. Можно ли использовать GUI-функции в рабочем пространстве функции? Например:

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 

Это событие-цикл будет выполняться бесконечно, так как обратный вызов не будет изменять myvar в функции. Вместо этого он создаст новый myvar в глобальной рабочей области.

ответ

5

Существует несколько способов использования build a GUI, например, с помощью App Designer, GUIDE или его программного программирования (я проиллюстрирую этот вариант ниже). Также важно знать different ways to define callback functions для ваших компонентов графического интерфейса пользователя и options available for sharing data between components.

Подход, в котором я неполный, использует nested functions в качестве обратных вызовов. Вот простой графический интерфейс в качестве примера:

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 

При запуске этого кода, отображаемый счетчик должен увеличиваться на единицу каждый раз, когда вы нажимаете на кнопку, так как вложенная функция increment имеет доступ к рабочей области make_useless_button и, таким образом, может изменить iCounter. Обратите внимание, что обратный вызов кнопки установлен на function handle на increment и что эта функция должна принимать по два аргумента по умолчанию: графический дескриптор для компонента пользовательского интерфейса, который вызвал обратный вызов, и структуру связанных данных события. Мы ignore them with the ~ в этом случае, так как мы их не используем.

Расширение выше подход к вашей проблеме, вы можете добавить свой цикл и изменить функцию обратного вызова, так что устанавливает переменную флаг ложь:

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 

drawnow здесь требуется, чтобы дать кнопку CallBack шанс для прерывания потока программы в цикле и изменения значения keepLooping.

1

Вы можете объявить переменную global в вашей функции и глобальную в коде GUI, конечно, если обратный вызов находится в отдельной функции, а не в строке. Я сделал это в небольшом скелетном графическом интерфейсе, который я использую для создания быстрой системы меню.

В коде выше вы можете добавить глобальное ключевое слово в первоначальной декларации, а также ваш инлайн обратного вызова т.е. «глобальной MyVar = ложь»

+0

OP необходимо будет изменить выходную переменную на что-то еще и создать «глобальный myvar» в базовом рабочем пространстве, чтобы это работало. – Azim 2008-11-07 17:29:26

+0

Действительно ли это единственный способ? Кажется, что это грубо использовать глобальные переменные для работы. – bastibe 2008-11-08 08:55:55

1

Я нашел решение этой проблемы. Функция обратного вызова должна изменить структуру дескриптора GUI. Эта структура может быть доступна как внутри обратного вызова и из функции без введения новых переменных в глобальной рабочей области:

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 

отмечают, что, поскольку в то время как петля будет обновлять только fig_handles при запуске, вы всегда будете иметь по крайней мере 0,2 секунды задерживают до тех пор, пока петля не поймает модификацию fig_handles.continue_loop