PRO test_gui
tlb = WIDGET_BASE(/COLUMN, TITLE='My Calculation'); top-level-base widget
base1 = WIDGET_BASE(tlb, /ROW); 첫번째 base widget (인자 A)
param_A_label = WIDGET_LABEL(base1, VALUE='Enter Parameter A (only number)')
param_A = WIDGET_TEXT(base1, XSIZE=8, /EDITABLE, UVALUE='param_A')
base2 = WIDGET_BASE(tlb, /ROW); 두번째 base widget (인자 B)
param_B_label = WIDGET_LABEL(base2, VALUE='Enter Parameter A (only number)')
param_B = WIDGET_TEXT(base2, XSIZE=8, /EDITABLE, UVALUE='param_B')
base3 = WIDGET_BASE(tlb, /ROW); 세번째 base widget (결과)
result_label = WIDGET_LABEL(base3, VALUE='Result')
result = WIDGET_TEXT(base3, XSIZE=8)
base4 = WIDGET_BASE(tlb, /ROW); 네번째 base widget (두 버튼)
start_bttn = WIDGET_BUTTON(base4, VALUE='Calculation Start !', UVALUE='start')
exit_bttn = WIDGET_BUTTON(base4, VALUE='Exit', UVALUE='exit')
WIDGET_CONTROL, tlb, /REALIZE; GUI를 구현하여 가시화
info = {param_A:param_A, param_B:param_B, result:result}; 공유정보 구조체
WIDGET_CONTROL, tlb, SET_UVALUE=info; 공유정보 구조체를 tlb의 user value로 저장
XMANAGER, 'test_gui', tlb; 이벤트 대기 체제 구축
END
PRO test_gui_event, event
WIDGET_CONTROL, event.top, GET_UVALUE=info; top-level-base widget의 UVALUE 추출
WIDGET_CONTROL, event.id, GET_UVALUE=uval; 이벤트가 발생한 widget의 UVALUE 추출
CASE uval OF; 어떤 widget에서 발생한 이벤트냐를 구분하여 작업 수행
'start' : BEGIN; 'Calculation Start !' 버튼을 누른 경우의 작업
WIDGET_CONTROL, info.param_A, GET_VALUE=fw
WIDGET_CONTROL, info.param_B, GET_VALUE=fh
result = FLOAT(fw)+FLOAT(fh)
result_str = STRTRIM(STRING(result, FORMAT='(F10.2)'), 2)
WIDGET_CONTROL, info.result, SET_VALUE=result_str
END
'exit' : WIDGET_CONTROL, event.top, /DESTROY; 'Exit' 버튼을 누른 경우의 작업
ELSE : RETURN; 그 외 이벤트에 대한 작업(아무것도 안하고 그냥 돌아감)
ENDCASE
END
GUI상에서 이벤트가 발생시 그 이벤트의 내용을 담은 구조체가 무조건 이 서브루틴으로 전달됩니다. 원래 메인루틴의 이름에 '_event'라는 문자가 붙은 이름의 서브루틴을 찾는 것이 기본설정입니다. 즉 여기서는 메인루틴의 이름이 'test_gui'이므로, 'test_gui_event'라는 이름의 서브루틴을 무조건 찾게 됩니다. 물론 각 widget에 대하여 EVENT_PRO라는 키워드로 다른 서브루틴을 지정해줄 경우에는, 그 widget에서 발생한 이벤트가 그 서브루틴으로 갑니다. 하지만 이벤트가 발생하는 widget임에도 불구하고, EVENT_PRO라는 키워드가 따로 지정이 안되어 있을 경우에는 무조건 이와 같은 이름의 루틴으로 이벤트 구조체가 전달된다는 점을 기억해둘 필요가 있습니다.
어쨌든 이 서브루틴의 맨 앞부분의 내용을 보면 먼저 event.top으로부터 UVALUE를 얻는다(Get)는 것인데, event.top은 이벤트가 발생된 widget의 최상위 레벨에 해당되는 widget을 의미하므로 바로 top-level-base widget이 됩니다. 그 다음 줄에서는 event.id로부터 UVALUE를 얻게 되는데, 여기서 event.id는 이벤트를 발생시킨 당사자 widget이 됩니다. 따라서 event.top으로부터 얻는 UVALUE는 앞서 메인루틴에서 정의했던 info라는 구조체가 될 것이고, event.id에서 얻는 UVALUE는 이벤트를 발생시키는 각 widget에 부여되어 있는 UVALUE가 됩니다. 이를 uval이라는 변수로 얻고, 이 uval이 뭐냐에 따라 해당 작업을 나눠서 수행하기 위하여 CASE라는 구문이 사용됩니다.
간단한 것 부터 보면, uval이 'exit'인 경우는 메인루틴에서 'Exit'라는 이름을 갖는 버튼에서 이벤트가 발생할 경우가 됩니다. 이 경우에는 GUI를 종료하겠다는 의미이므로 event.top를 /DESTROY한다는 내용이 들어간 것입니다. 그리고 uval이 'start'인 경우가 바로 우리가 원하는 연산을 수행하여 그 결과를 result라는 텍스트 widget에 표출하는 작업을 수행합니다. 이 작업의 내용을 보면 연산의 대상이 될 숫자값들을 param_A, param_B 두 텍스트 widget에서 얻고(문자형으로 얻어짐), 이 값을 실수형으로 변환하여 덧셈 연산을 수행한 다음, 그 결과값을 문자형으로 변환하여 result라는 텍스트 widget에 부여하는 순서로 진행됩니다.
대략 이와 같은 내용이 됩니다. 이 예제코드는 아래에 첨부합니다. 더 자세한 내용은 앞서 언급된 PDF문서의 내용을 참조하시길 바랍니다. 대략적으로 설명을 해보았지만, IDL로 앱을 만드는 하나의 예로서 소개를 해보았습니다.
'IDL > Widget' 카테고리의 다른 글
| IDL에서 GUI 프로그래밍을 해보고자 한다면? (내용 업데이트) (0) | 2018.08.13 |
|---|---|
| IDL App 실행파일 및 배포용 패키지 만들기 [2] (0) | 2016.06.21 |
| IDL App 실행파일 및 배포용 패키지 만들기 [1] (0) | 2016.06.20 |
| 두 개의 그래픽창을 갖는 GUI 만들어보기 (0) | 2013.01.30 |