MATLAB Language
MATLAB 사용자 인터페이스
수색…
사용자 인터페이스 주변의 데이터 전달
대부분의 고급 사용자 인터페이스는 사용자가 사용자 인터페이스를 구성하는 다양한 기능 사이에서 정보를 전달할 수 있어야합니다. 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
setappdata
와 getappdata
를 사용하여 그래픽 핸들 내에서 값을 저장하고 검색 할 수 있습니다. 이러한 메서드를 사용하면 모든 저장된 데이터를 포함하는 전체 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. (빠른 프로토 타이핑,
guidata
및set/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
이 예제를 이해하려면 다음을 수행하십시오.
- 위 코드를 호출 한 새 파일에 붙여넣고
interruptibleUI.m
이라는 이름으로 저장합니다. 코드가 파일의 첫 번째 줄 에서 시작되도록합니다 (첫 번째 방법이 작동하는 것이 중요합니다). - 스크립트를 실행하십시오.
- 계산을 클릭하고 잠시 후 일시 중지 # 1 또는 일시 중지 # 2를 클릭하십시오.
-
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
에 큰 데이터가있는 필드가 많은 경우 결과가 변경됩니다.