수색…


사용자 인터페이스 주변의 데이터 전달

대부분의 고급 사용자 인터페이스는 사용자가 사용자 인터페이스를 구성하는 다양한 기능 사이에서 정보를 전달할 수 있어야합니다. MATLAB에는 이렇게하는 여러 가지 방법이 있습니다.


guidata

MATLAB의 자체 GUI 개발 환경 (GUIDE) 은 콜백간에 데이터를 전달하기 위해 handles 이라는 struct 를 사용합니다. 이 struct 는 사용자 지정 데이터뿐만 아니라 다양한 UI 구성 요소에 대한 모든 그래픽 핸들을 포함합니다. handles 을 자동으로 전달하는 GUIDE 생성 콜백을 사용하지 않는 경우 guidata 사용하여 현재 값을 검색 할 수 있습니다

% hObject is a graphics handle to any UI component in your GUI
handles = guidata(hObject);

이 데이터 구조에 저장된 값을 수정하려면 수정할 수 있지만 변경 사항을 다른 콜백에서 볼 수 있도록 hObject 에 저장해야합니다. guidata 두 번째 입력 인수를 지정하여 저장할 수 있습니다.

% Update the value
handles.myValue = 2;

% Save changes
guidata(hObject, handles)

궁극적으로 데이터가 hObject 포함하는 hObject 내에 저장되기 때문에 hObject 의 값은 동일한 figure 내의 UI 구성 요소 인 한 중요하지 않습니다.

대상 :

  • handles 구조를 저장하면 GUI 구성 요소의 모든 핸들을 저장할 수 있습니다.
  • 대부분의 콜백이 액세스해야하는 "작은"다른 변수를 저장합니다.

권장되지 않음 :

  • 모든 콜백과 하위 함수가 액세스 할 필요가없는 큰 변수를 저장 ( setappdata / getappdata 를 사용).

setappdata / getappdata

guidata 접근 방식과 getappdata setappdatagetappdata 를 사용하여 그래픽 핸들 내에서 값을 저장하고 검색 할 수 있습니다. 이러한 메서드를 사용하면 모든 저장된 데이터를 포함하는 전체 struct 가 아니라 원하는 값만 검색 할 수 있다는 이점이 있습니다. 키 / 값 저장소와 비슷합니다.

그래픽 객체 내에 데이터를 저장하려면

% Create some data you would like to store
myvalue = 2

% Store it using the key 'mykey'
setappdata(hObject, 'mykey', myvalue)

그리고 다른 콜백 내에서 동일한 값을 검색하기 위해

value = getappdata(hObject, 'mykey');

참고 : getappdata 를 호출하기 전에 저장된 값이 없으면 빈 배열 ( [] )을 반환합니다.

유사 guidata 데이터가 포함 된 도면에 저장된 hObject .

대상 :

  • 모든 콜백 및 하위 함수에서 액세스 할 필요가없는 큰 변수를 저장합니다.

UserData

모든 그래픽 핸들에는 사용자가 원하는 모든 데이터를 포함 할 수있는 UserData 라는 특별한 속성이 있습니다. 셀 배열, struct 또는 스칼라를 포함 할 수 있습니다. 이 속성을 활용하고 주어진 그래픽 핸들과 연관시킬 데이터를이 필드에 저장할 수 있습니다. R2014b 이상을 사용하는 경우 그래픽 객체 또는 점 표기법의 표준 get / set 메소드를 사용하여 값을 저장하고 검색 할 수 있습니다.

% Create some data to store
mydata = {1, 2, 3};

% Store it within the UserData property
set(hObject, 'UserData', mydata)

% Of if you're using R2014b or newer:
% hObject.UserData = mydata;

그런 다음 다른 콜백 내에서이 데이터를 검색 할 수 있습니다.

their_data = get(hObject, 'UserData');

% Or if you're using R2014b or newer:
% their_data = hObject.UserData;

대상 :

  • 제한된 범위의 변수 저장 (변수가 저장된 객체 또는 변수와 직접 관계가있는 객체에서만 사용되는 변수)

중첩 된 함수

MATLAB에서 중첩 된 함수는 부모 함수에 정의 된 모든 변수를 읽고 수정할 수 있습니다. 이런 식으로 중첩 된 함수로 콜백을 지정하면 main 함수에 저장된 모든 데이터를 검색하고 수정할 수 있습니다.

function mygui()    
    hButton = uicontrol('String', 'Click Me', 'Callback', @callback);

    % Create a counter to keep track of the number of times the button is clicked
    nClicks = 0;

    % Callback function is nested and can therefore read and modify nClicks
    function callback(source, event)
        % Increment the number of clicks
        nClicks = nClicks + 1;

        % Print the number of clicks so far
        fprintf('Number of clicks: %d\n', nClicks);
    end
end

대상 :

  • 작고 간단한 GUI. (빠른 프로토 타이핑, guidataset/getappdata 메소드 구현이 필요 guidata ).

권장되지 않음 :

  • 중형, 대형 또는 복합 GUI.

  • GUIDE 생성 된 GUI.


명시 적 입력 인수

콜백 함수에 데이터를 보내고 콜백 내에서 데이터를 수정할 필요가없는 경우 신중하게 만들어진 콜백 정의를 사용하여 콜백에 데이터를 전달하는 것을 항상 고려할 수 있습니다.

입력을 추가하는 익명의 함수를 사용할 수 있습니다.

% Create some data to send to mycallback
data = [1, 2, 3];

% Pass data as a third input to mycallback
set(hObject, 'Callback', @(source, event)mycallback(source, event, data))

또는 셀 배열 구문을 사용하여 콜백을 지정하고 추가 입력을 지정할 수 있습니다.

set(hObject, 'Callback', {@mycallback, data})

대상 :

  • 콜백에 일부 작업을 수행하기 위해 data 가 필요하지만 data 변수를 수정하여 새 상태로 저장할 필요가없는 경우.

UI에서 콜백 실행을 일시 중지하는 버튼 만들기

때로는 코드 실행을 일시 중지하여 응용 프로그램의 상태를 검사하려고합니다 ( 디버깅 참조). MATLAB 편집기를 통해 코드를 실행하는 경우 UI의 "일시 중지"버튼을 사용하거나 Ctrl + c (Windows의 경우)를 눌러 수행 할 수 있습니다. 그러나 계산이 GUI (일부 uicontrol 의 콜백을 통해)에서 시작된 경우이 방법은 더 이상 작동하지 않으며 다른 콜백을 통해 콜백이 중단 되어야합니다. 다음은이 원리의 시연입니다.

function interruptibleUI
dbclear in interruptibleUI % reset breakpoints in this file
figure('Position',[400,500,329,160]); 

uicontrol('Style', 'pushbutton',...
          'String', 'Compute',...
          'Position', [24 55 131 63],...
          'Callback', @longComputation,...
          'Interruptible','on'); % 'on' by default anyway
      
uicontrol('Style', 'pushbutton',...
          'String', 'Pause #1',...
          'Position', [180 87 131 63],...
          'Callback', @interrupt1);       

uicontrol('Style', 'pushbutton',...
          'String', 'Pause #2',...
          'Position', [180 12 131 63],...
          'Callback', @interrupt2);    

end

function longComputation(src,event)
  superSecretVar = rand(1);
  pause(15);
  print('done!'); % we'll use this to determine if code kept running "in the background".
end

function interrupt1(src,event) % depending on where you want to stop
  dbstop in interruptibleUI at 27 % will stop after print('done!');
  dbstop in interruptibleUI at 32 % will stop after **this** line.
end

function interrupt2(src,event) % method 2
  keyboard;
  dbup; % this will need to be executed manually once the code stops on the previous line.
end

이 예제를 이해하려면 다음을 수행하십시오.

  1. 위 코드를 호출 한 새 파일에 붙여넣고 interruptibleUI.m 이라는 이름으로 저장합니다. 코드가 파일의 첫 번째 줄 에서 시작되도록합니다 (첫 번째 방법이 작동하는 것이 중요합니다).
  2. 스크립트를 실행하십시오.
  3. 계산을 클릭하고 잠시 후 일시 중지 # 1 또는 일시 중지 # 2를 클릭하십시오.
  4. superSecretVar 의 값을 찾을 수 있는지 확인하십시오.

"handles"구조체를 사용하여 데이터 전달하기

이것은 GUI의 handles 구조에 저장된 값을 변경하는 두 개의 버튼이있는 기본 GUI의 예입니다.

function gui_passing_data()
    % A basic GUI with two buttons to show a simple use of the 'handles'
    % structure in GUI building

    %  Create a new figure.
    f = figure();

    % Retrieve the handles structure
    handles = guidata(f);

    % Store the figure handle
    handles.figure = f;

    % Create an edit box and two buttons (plus and minus), 
    % and store their handles for future use
    handles.hedit  = uicontrol('Style','edit','Position',[10,200,60,20] , 'Enable', 'Inactive');

    handles.hbutton_plus  = uicontrol('Style','pushbutton','String','+',...
               'Position',[80,200,60,20] , 'Callback' , @ButtonPress);

    handles.hbutton_minus  = uicontrol('Style','pushbutton','String','-',...
               'Position',[150,200,60,20] , 'Callback' , @ButtonPress);

    % Define an initial value, store it in the handles structure and show
    % it in the Edit box
    handles.value = 1;
    set(handles.hedit , 'String' , num2str(handles.value))

    % Store handles
    guidata(f, handles);



function  ButtonPress(hObject, eventdata)
    % A button was pressed
    % Retrieve the handles
    handles = guidata(hObject);

    % Determine which button was pressed; hObject is the calling object
    switch(get(hObject , 'String'))
        case '+'
            % Add 1 to the value
            handles.value = handles.value + 1;
            set(handles.hedit , 'String', num2str(handles.value))
        case '-'
            % Substract 1 from the value
            handles.value = handles.value - 1;
    end

    % Display the new value
    set(handles.hedit , 'String', num2str(handles.value))

    % Store handles
    guidata(hObject, handles);

예제를 테스트하려면 gui_passing_data.m 이라는 파일에 저장하고 F5 키를 gui_passing_data.m 실행하십시오. 이 간단한 경우에는 편집 상자의 String 속성에서 직접 액세스 할 수 있으므로 핸들 구조에 값을 저장하지 않아도됩니다.

사용자 인터페이스 주변에서 데이터를 전달할 때 성능 문제

GUI 함수와 콜백 사이에 데이터를 전달하는 두 가지 주요 기술 : setappdata / getappdata 및 guidata ( 자세한 내용 참조 ). 전자는 시간이 효율적이므로 큰 변수에 사용해야합니다. 다음 예제는 두 가지 방법의 효율성을 테스트합니다.

간단한 버튼이있는 GUI가 생성되고 큰 변수 (10000x10000 double)가 guidata와 setappdata와 함께 저장됩니다. 버튼은 실행을 타이밍을 지정하는 동안 두 가지 방법을 사용하여 변수를 다시로드하고 저장합니다. setappdata를 사용하여 실행 시간 및 백분율 개선이 명령 창에 표시됩니다.

function gui_passing_data_performance()
    % A basic GUI with a button to show performance difference between
    % guidata and setappdata

    %  Create a new figure.
    f = figure('Units' , 'normalized');

    % Retrieve the handles structure
    handles = guidata(f);

    % Store the figure handle
    handles.figure = f;

    handles.hbutton = uicontrol('Style','pushbutton','String','Calculate','units','normalized',...
               'Position',[0.4 , 0.45 , 0.2 , 0.1] , 'Callback' , @ButtonPress);

    % Create an uninteresting large array
    data = zeros(10000);

    % Store it in appdata
    setappdata(handles.figure , 'data' , data);

    % Store it in handles
    handles.data = data;

    % Save handles
    guidata(f, handles);



function  ButtonPress(hObject, eventdata)

    % Calculate the time difference when using guidata and appdata
    t_handles = timeit(@use_handles);
    t_appdata = timeit(@use_appdata);

    % Absolute and percentage difference
    t_diff = t_handles - t_appdata;
    t_perc = round(t_diff / t_handles * 100);

    disp(['Difference: ' num2str(t_diff) ' ms / ' num2str(t_perc) ' %'])




function  use_appdata()  

    % Retrieve the data from appdata
    data = getappdata(gcf , 'data');

    % Do something with data %

    % Store the value again
    setappdata(gcf , 'data' , data);


function use_handles()

    % Retrieve the data from handles
    handles = guidata(gcf);
    data = handles.data;

    % Do something with data %

    % Store it back in the handles
    handles.data = data;
    guidata(gcf, handles);

제온 [email protected] GHz에서 나는 Difference: 0.00018957 ms / 73 % 얻습니다 Difference: 0.00018957 ms / 73 % , 따라서 getappdata / setappdata를 사용하면 73 %의 성능 향상을 얻었습니다! 10x10 이중 변수를 사용하면 결과가 변경되지 않지만 handles 에 큰 데이터가있는 필드가 많은 경우 결과가 변경됩니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow