6. 구성요소에 활력 불어넣기
1. 블록에디터를 오픈하고 좌측에 위치한 사용자 블록(My Blocks)탭을 선택하면 상기 디자이너 창에서 작업한 클록(Clock1), 이미지(Image) 및 스크린(Screen1) 등에 각각 대응하는 복수의 드로워(Drawer)가 나타난다. 이외에도, 나중에 설명하는 바와 같이 변수블록 등을 정의할 때에 자동생성되는 블록을 저장하는 사용자정의(My Definitions)드로워가 나타난다.
2. 이제부터는, 본 예제에서 실제로 사용되는 블록에 대해서 설명한다.
2-1. 우선, 내장블록(Built-In)탭의 정의(Definition)드로워에 있는 변수블록(def variable)을 사용하여, 다수의 이미지 파일을 임시 저장하는 이미지리스트(Imagelist)를 정의한다.
2-1-1. 구체적으로는, 내장블록(Built-In)탭의 정의(Definition)드로워를 열면, 사용자가 정의하기 위해 사용하는 복수의 블록이 수직방향으로 나열되어 있다. 이중에서 변수블록(def variable)을 작업영역으로 드래그한다.
2-1-2. 대안으로서, 블록에디터의 우측의 넓은 영역을 차지하는 작업영역의 임의의 장소에 마우스의 커서를 놓고 마우스의 좌측버튼을 클릭하면 내장블록(Built-In)탭의 복수의 드로워(Drawer)에 대응하는 수평메뉴(Defin…, Text, Lists, Math, Logic, Control, Colors)가 나타나고, 이 중에서 정의메뉴(Defin…)를 선택하여 클릭하면 아래의 스크린샷에 나타난 바와 같이 내장블록(Built-In)탭의 정의(Definition)드로워내의 블록에 대응하는 수직메뉴(procedureWithResult, procedure, variable, name, |)가 나타난다. 여기서, 수직메뉴중에서 변수메뉴(variable)를 선택하여 클릭하면, 변수블록(def variable)이 작업영역에 자동생성된다.
참고 사항: 이 변수블록은 이전에 설명한 바와 같이 내장블록(Built-In)탭의 정의(Definition)드로워에서 변수블록(def variable)을 작업영역으로 드래그한 것과 마찬가지의 결과가 된다.
2-1-3. 상기 두 가지 방법 중 어느 하나를 사용하여도 다음의 스크린샷과 같은 변수블록을 블록에디터의 작업영역에 생성한다.
2-1-4. 이 변수블록(def variable)에서 variable을 더블클릭하여 ImageList로 정정하면 이미지파일의 임시저장장소인 이미지리스트가 된다.
2-2. 다음에, 내장블록(Built-In)탭의 리스트(Lists)드로워를 열고 리스트만들기블록(make a list)을 작업영역으로 드래그한다.
대안으로서, 에디터의 작업영역에 마우스 커서를 놓고 마우스의 좌측버튼을 클릭하면 수평메뉴가 나타나고 리스트메뉴(Lists)를 선택하여 클릭하면 수직메뉴가 나타나고 리스트만들기메뉴(make a list)를 선택하여 클릭한다.
이들 두가지 방법중 어느 하나를 사용하여 리스트만들기블록(make a list)을 얻는다.
2-3. 다음에, 내장블록(Built-In)탭의 텍스트(Text)드로워를 열고 텍스트블록(text text)을 작업영역으로 드래그한다.
대안으로서, 에디터의 작업영역에 마우스 커서를 놓고 마우스의 좌측버튼을 클릭하면 수평메뉴가 나타나고 텍스트메뉴(Text)를 선택하여 클릭하면 수직메뉴가 나타나고 텍스트메뉴(text)를 선택하여 클릭한다.
이들 두가지 방법중 어느 하나를 사용하여 텍스트(text text)를 생성한다.
2-3-1. 다음에, text를 더블클릭하여 newyearbow01.png로 정정하고, 정정된 텍스트블록을 3회 복사하여 작업영역에 붙여 넣는다. 이와 같이 복사한 3개의 텍스트블록의 텍스트(introduction01.png)를 각각 더블클릭하여 텍스트(introduction02.png, introduction03.png, introduction04.png)로 정정한다. 이에 대한 스크린샷은 다음과 같다.
2-4. 블록에디터의 작업영역에서, 상기 이미지리스트블록(def ImageList)에 리스트만들기블록(call make a list item)을 플러그인한다. 이와 같이 플러그인한 리스트만들기블록(call make a list item)의 소켓(item)에 텍스트블록(introduction01.png, introduction02.png, introduction03.png, introduction04.png)을 순차적으로 플러그인한다.
참고사항: 텍스트블록(introduction01.png, introducton02.png, introduction03.png, introduction04.png)에는 디자이너창에서 업로드된 이미지파일명칭이 기재되어 있다. 이미지의 파일명칭에는 확장자를 포함한다.
3. 다음에, 외부에 드러나지 않는 히든 인덱스 변수(Hidden Index Variable)를 정의한다.
3-1. 이 변수는 이미지리스트의 이미지파일명의 순서를 나타낸다. 예를 들면, 다음에 설명하는 클록 타이머의 시간주기마다 상기 이미지리스트의 이미지파일을 순차적으로 변경하기 위해서는,현재 어느 이미지파일이 나타나는 지를 기억할 필요가 있다. 이와 같이 프로그램에서 기억할 필요가 있는 경우에는 사용자가 변수를 직접 정의하여야 한다. 이 경우에는 현재 이미지의 순차번호(즉, 이미지리스트의 인덱스)를 기억할 필요가 있다.
3-2. 이미지리스트블록과 마찬가지로, 내장블록(Built-In)탭의 정의(Definition)드로워를 열고 변수블록(def variable)을 작업영역으로 드래그한다. 이 변수블록(def variable)에서variable을 더블클릭하여 ImageIndex로 정정한다.
참고사항: 상기 블록에서 직사각형상의 노란색 표시는 이 블록의 소켓에 초기화하고자하는 번호블록을 연결하면 사라진다.
3-3. 내장블록(Built-In)탭의 수학(Math)드로워를 열고, 숫자블록(number 123)을 선택하여 클릭한다. 이 숫자블록(number 123)에서 123을 더블클릭하고 1로 변경한다.
3-4. 상기 이미지인덱스블록(def ImageIndex)에 숫자블록을 플러그인한다.
참고 사항: 상기 설명한 변수는 메모리 셀에 임시 저장된다. 이외에도, 구성요소의 속성이 메모리 셀에 임시 저장된다. 여기서, 메모리 셀에 임시 저장되는 변수와 구성요소의 속성은 앱을 실행할 때에는 메모리 셀에 기억되어 있지만 앱을 닫으면 메모리셀에 기억된 변수나 구성요소의 속성은 모두 사라진다. 이에 반해서, 어느 상태에서도 영구적으로 저장가능한 소형데이터베이스(TinyDB)와 소형웹데이터베이스(TinyWebDB)가 있다. 이에 대해서는 나중에 상세하게 설명한다. 이외에도 퓨전테이블이 있다.
4. 앱이 시작할 때 스크린을 초기화하는 이벤트에 의해 트리거되는 스크린초기화블록(Screen1.initialize)의 기능블록조합에 대해 설명한다.
4-1. 사용자블록(My Blocks)탭을 선택하고 스크린(Screen1)드로워를 열고 스크린초기화블록(Screen1.Initialize)을 작업영역으로 드래그한다.
4-2. 사용자블록(My Blocks)탭을 선택하고 사용자정의(My Definitions)드로워를 열고 전역이미지리스트(global ImageList)를 작엽영역에 드래그한다.
참고사항: 이미지리스트와 이미지인덱스를 상기한 바와 같이 만들 때에 사용자블록(My Blocks)탭의 사용자정의(My Definitions)드로워에 전역 이미지리스트(global ImageList)와 전역 이미지인덱스(global ImageIndex)가 자동으로 생성된다.
4-3. 숫자블록에 대해서는 이미 설명하였으므로 이에 대한 설명은 생략한다.
4-4. 내장블록(Built-In)탭의 리스트(Lists)드로워를 열고 리스트 아이템 선택 호출블록(call select list item list index)을 작업영역으로 드래그한다.
4-5. 사용자블록(My Blocks)탭을 선택하고 이미지(Image)드로워를 열고 이미지의 그림설정블록(set Image.Picture to)을 작업영역으로 드래그한다.
4-6. 상기 4개의 블록을 다음의 스크린샷과 같이 조합한다. 즉, 리스트 아이템 호출블록(call select list item list index)의 소켓(list, index)에 각각 전역 이미지리스트블록(global ImageList)과 숫자블록(number 1)을 플러인한 블록조합을 이미지의 그림블록(set Image.Picture to)의 소켓(to)에 플러그인한다.
4-7. 이와 같이 플러그인한 블록조합을 스크린초기화블록에 조합한다. 구체적으로는, 이미지리스트(global ImageList)에서 인덱스 1에 대응하여 선택된 첫번째 이미지를 그림으로 설정하는 기능을 스크린의 초기화시에 트리거하는 블록조합은 다음의 스크린샷과 같다.
참고 사항 1: 상기 블록조합의 논리적인 해석은 우측의 블록부터 시작하여 좌측블록의 방향으로 해석한다. 즉, 상기 스크린초기화블록의 조합을 해석하면, 이미지리스트에서 인덱스가 1인 그림파일을 선택하여 이미지의 그림으로 설정한다.
참고 사항 2: 이벤트 핸들러 타입에는, 상기 설명하는 바와 같이 화면을 초기화하는 초기화이벤트핸들러와 다음에 설명하는 클록타이머를 이용하는 타이머이벤트핸들러가 있다. 이외에도 버튼클릭을 이용하는 사용자초기화 이벤트 핸들러 및 안드로이드폰이 텍스트를 수신할 때 사용하는 외부 이벤트 핸들러도 있다.
5. 클록의 타이머에 대해서 설명한다.
복수의 이미지(인사말)를 일정한 주기로 반복하면 4개의 인사말을 일정한 주기(시간간격)으로 순환하면서 나타낼 수 있다. 이를 달성하기 위해서는 클록타이머이벤트핸들러를 사용한다.
5-1. 사용자블록(My Blocks)탭을 선택하고 클록(Clock1)드로워를 열고 클록의 타이머(Clock1.Timer)를 작업영역으로 드래그한다.
5-2. 클록의 타이머의 주기마다 인사말의 이미지파일을 변경하기 위해 이미지인덱스를 증가시킨다. 이에 대해 이하 상세설명한다.
5-2-1. 상기에서 이미 설명한 바와 같이, 변수블록인 이미지인덱스블록(ImageIndex)의 형성시에 사용자블록(My Blocks)탭의 사용자정의(My Definitions)드로워안에 전역 이미지인덱스블록(global ImageIndex)과 전역 이미지인덱스 설정블록(set global ImageInedx to)이 자동생성된다.
따라서, 사용자블록(My Blocks)탭의 사용자정의(My Defintions)드로워를 열고, 자동생성된 전역 이미지인덱스 설정블록(set global imageIndex to)을 작업영역으로 드래그한다.
5-2-2. 또한, 내장블록(Built-In)탭의 수학(Math)드로워를 열고 숫자블록(number 123)을 작업영역으로 드래그하고 숫자블록의 123을 더블클릭하여 1로 정정한다.
5-2-3. 수학(Math)드로워를 열고 플러스블록(+)을 작업영역으로 드래그한다.
5-2-4. 또한 사용자블록(My Blocks)컬럼의 정의(My Definitions)드로워를 열고 전역이미지인덱스블록(global ImageIndex)을 작업영역으로 드래그한다.
5-2-5. 플러스블록을 사용하여 전역이미지인덱스값에 1을 가산하는 블록을 조합한다.
5-2-6. 전역이미지인덱스설정블록(set global ImageIndex to)의 소켓(to)에 상기 전역이미지인텍스값의 가산블록을 플러그인한다.
5-3. 상기에서 설명한 바와 같이, 전역이미지리스트(global ImageList)에서 전역이미지인덱스(global ImageIndex)에 의거하여 선택된 이미지를 그림으로 설정하는 블록조합은 다음의 스크린샷과 같다. 이에 대한 상세설명은 상기에서 설명한 것과 유사하므로 생략한다.
5-4. 클록타이머이벤트핸들러에 상기 블록조합 2개를 조합한다. 즉, 이미지인덱스를 1 만큼씩 증가 시키고 이미지리스트에서 이미지인덱스에 의거하여 선택한 이미지(이미지파일)를 이미지의 그림(set Image.Picture to)으로 설정한다. 여기서, 전역이미지인덱스(global ImageIndex)는 전역이미지리스트(global ImageList)의 아이템 순서와 같다.
이를 구현한 블록조합의 스크린샷은 아래와 같다.
5-5. 그런데, 이와 같은 상태에서 에뮬레이터에 접속하면 이미지리스트의 개수에 관계없이 이미지인덱스가 계속 증가하여 이미지리스트의 개수를 초과하게 되어, 리스트 아이템(list item)을 선택하라는 아래와 같은 경고 상자가 나타난다.
6. 이를 보완하기 위해, 상기 클록의 타이머이벤트핸들러블록에, 조건블록(if)을 사용하여 이미지인덱스가 4인 경우에는 클록타이머가 중지하도록 설정하는 블록을 부가한다. 부가하는 블록에 대해 구체적으로 이하 설명한다.
6-1. 내장블록(Built-In)탭의 제어(Control)드로워를 열고 조건블록(if)을 작업영역으로 드래그한다.
6-2. 내장블록(Built-In)탭의 수학(Math)드로워를 열고 숫자블록(number 123)을 작업영역으로 드래그하고 숫자블록의 123을 더블클릭하여 4로 정정한다.
6-3. 수학(Math)드로워를 열고 이퀄블록(=)을 작업영역으로 드래그한다.
6-4. 또한 사용자블록(My Blocks)컬럼의 사용자정의(My Definitions)드로워를 열고 전역이미지인덱스블록(global ImageIndex)을 작업영역으로 드래그한다.
6-5. 이퀄블록을 사용하여 전역이미지인덱스값이 4인 블록을 만든다.
6-6. 다음에, 사용자블록(My Blocks)탭을 선택하고 클록(Clock1)드로워를 열고 클록의 타이머구동설정블록(set Clock1.TimerEnabled to)을 작업영역으로 드래그한다.
6-7. 내장블록(Built-In)탭의 논리(Logic)드로워를 열고 불 논리(Boolean logic)의 거짓블록(false)을 작업영역으로 드래그한다.
6-8. 타이머구동설정블록(set Clock1.TimerEnabled to)의 소켓(to)에 거짓블록을 플러그인한다.
6-9. 조건블록(if)의 테스트소켓(test)에는 이미지인덱스값이 4로 되는 조합블록을 플러그인하고, 본문의 소켓(then-do)에는 클록의 타이머동작이 정지하는 조합블록을 플러그인한다. 따라서, 이미지인덱스가 4인 경우에 클록타이머가 정지하는 조건블록을 완성한다.
6-10. 상기 조건블록을 클록의 타이머이벤트핸들러에 추가한 조합블록을 나타낸 스크린샷은 다음과 같다.
7. 이 경우에 에러없이 4종류의 인사말이 1회 진행한다. 인사말의 표시를 계속해서 반복하기를 원하는 경우에는, 클록의 타이머가 동작하지 않도록 하는 대신에, 이미지 인덱스가 4로 될 때마다 이미지인덱스를 0으로 정정하는 조건블록을 사용한다.
이 조건블록은, 이미지인덱스를 정정하여 사용하는 블록이기 때문에, 이미지인덱스를 증가시키는 블록에 선행하여 위치시킨다. 그 결과의 스크린샷은 다음과 같다.
8. 이에 관련하여, 이미지리스트에 이미지파일의 개수를 임의로 추가하는 경우에는 클록의 타이머에서도 이미지인덱스의 번호(number 4)도 변경하여야 하는 번거로움이 있다. 프로그램이 방대해지는 경우 수작업으로 완전히 변경하지 못하여 프로그램에 버그가 발생하는 경우가 흔히 있다. 이러한 버그를 철저하게 대비할 수 있는 한층 더 일반적인 방식을 사용하는 것이 바람직하다. 구체적으로는, 조건블록(if)에서 이미지인덱스를, 4로 고정하는 대신에, 이미지리스트의 이미지파일의 전체개수로 수정하면, 상기한 버그를 완벽하게 차단할 수 있다. 즉, 이미지 동작의 프로그램을 한층 더 유연하게 할 수 있다.
8-1. 이에 대한 블록의 조합에 있어서 이미지리스트에 저장된 이미지파일의 전체개수를 나타내는 이미지인덱스 전체의 개수에 해당하는 리스트의 길이블록(call length of list list)의 소켓(list)에, 전역 이미지리스트블록(global ImageList)을 플러그인한 블록에 대해서만 설명한다. 나머지 설명은 중복되므로 생략한다.
8-1-1. 내장블록(Built-In)탭의 리스트(lists)드로워를 열고 리스트의 길이블록(call length of list list)을 작업영역으로 드래그한다.
8-1-2. 사용자블록(My Blocks)탭의 사용자 정의(My Definitions)드로워를 열고 전역 이미지리스트(global ImageList)을 작업영역으로 드래그한다.
8-1-3. 리스트의 길이블록(call length of list list)의 소켓(list)에 전역 이미지리스트블록(global ImageList)을 플러그인한 조합블록의 스크린샷은 다음과 같다.
8-2. 상기한 바와 같이 리스트의 길이블록(call length of list list)의 소켓(list)에 전역 이미지리스트블록(global ImageList)을 플러그인한 조합블록을 사용하여 보완한 클록타이머의 이벤트핸들러의 스크린샷은 다음과 같다.
9. 참고로, 상기 블록을 수정하는 과정에서 클록 타이머의 조건 및 이미지인덱스에 대해 라이브 테스트하고자 하는 경우에는, 에뮬레이터 또는 안드로이드 폰이 에디터블록에서 라이브로 연결된 상태에서, 이미지인덱스정의블록(def ImageIndex)과 조건블록(if) 위에 각각 순차적으로 마우스커서를 올려놓고 마우스의 오른쪽버튼을 클릭하면 세로메뉴가 나타나고, 이 세로메뉴에서 메뉴(watch)를 선택하여 클릭하면 블록의 좌측상부에 백색의 사각형이 형성되고, 이 사각형을 클릭하면 말풍선이 나타난다. 이벤트가 트리거되면(이 예제에서는, 앱을 시작하면), 이미지인덱스 정의블록(def ImageIndex)에서는 이미지파일의 인덱스번호(1, 2, 3, 4)가 순차적으로 나타나고 조건블록(if)에서는 1분 간격으로 문자(done)가 나타난다. 이것은 버그의 발생시에 그 원인을 간편하게 찾을 수 있는 메릿이 있는 라이브테스트이다.
10. 지금까지의 설명한 블록을 종합하여 나타내면 다음의 스크린샷과 같다.
5. 요약
이번 장에서는 변수블록을 정의하는 방법을 배웠다. 변수블록을 정의하는 방법에 따라 블록의 조합전체가 복잡하게 될 수 있고 간단하게 될 수도 있다. 처음부터 간단하게 되도록 변수블록을 정의하는 것은 경험에 비추어 볼때 쉽지 않다. 한참 진행하다 보면, 의외로 간단한 발상이 직관적으로 떠오를 수 있다. 그때까지는 열심히 공부하는 것이외에는 대안이 없다. 복잡하게 되어도 그대로 진행하다 보면 새로운 아이디어가 떠오르는 경우가 많다.
또한,앱을 실행할 때 초기화하는 방법 및 이미지를 연속적으로 나타내기 위해 타이머를 사용하는 방법을 배웠다. 여기서는 비교적 간단한 예를 다루었지만 타이머를 연동하는 방법을 깊게 알면 알수록 신기한 아이디어가 연상되어 생각데로 모든 것을 해결할 수 있는 경우도 많다고 생각한다.
이 예제는 인사하는 문구를 사용하고 있지만 개인적으로는 새배하는 4개의 연속동작을 사용하여 어플을 만들었으나 공개하지 않는 이유는 저작권과 연관될 것 같은 생각이 들어 방향전환을 한 것이다. 연속동작은 이미지의 수에 따라 그 정도를 높힐수 도 있다.
참고사항 1: 초보자에게는 설명이 어려울 수 있다. 하고 싶은 의욕만 있다면 설명을 전부 무시하고 디자이너창에서 구성요소를 따라하고, 블록에디터창에서 블록을 끌어다 놓으면 된다. 성취감을 느낄수 있다.
참고사항 2: 그래도 어려우면, 제 4 장 스크린 초기화, 변수 및 타이머 1 (준비단계 및 학습소개)에 첨부된 압축파일을 풀지말고 제 2 장 앱인터의 레이아웃 1 (사용자 프로젝트창)의 4-3에서 설명한 업로드 소스버튼난을 참조하여 업로드하면 디자이너창 및 블록에디터창에서 지금 까지 복잡하게 설명한 블록의 조합을 볼수 있다. 이를 참고하면 쉽게 해결될 수 있다.
댓글 없음:
댓글 쓰기