Past/Matlab GUI

Matlab GUI로 스타크래프트 빌드메이커 제작 #2/6 - M파일 초기조건 설정

Ratatui 2017. 12. 12. 20:55

<프로그램 설명 포스팅 링크>


M파일이 처음 생성되고 나면
GUI실행에 필요한 모든 코드가 자동으로
입력되지만, 아무 역할도 할 수는 없다.


프로그램의 정상적인 구동을 위해서는
알맞는 코딩을 해줘야 한다.


이제부터 프로그램의 코딩에 대해서
초기조건 설정부터 알아보자.


초기조건을 입력하는 위치는 코드 앞부분
'파일이름_OpeningFcn(...)' 이 있는 줄 다음이다.
이 위치에서 모든 객체들의 초기조건과
프로그램 구동에 필요한 전역변수를 선언한다.




55~59번 줄을 먼저 보면 for문 안에
한 눈에 잘 들어오지 않는 코드가 있다.


실제 빌드오더에 이미지가 들어가는
'Axes'객체는 초기조건을 설정하지 않으면
격자 표시가 되어있어서 깔끔하지 않다.
이 프로그램에서 최대로 입력할 수 있는
빌드오더는 33개이니 for문을 33번 돌려서
33개의 'Axes'에 'axis off' 명령을 하는 것이다.


그런데 왜 저렇게 복잡하게 코드를 썼냐하면
바로 eval함수의 특성 때문이다.
eval함수는 괄호 안의 글을 선언하는 역할이다.


axes1~axes33까지 for문을 이용하여
명령을 하려면 문자와 숫자를 같이 표시하려고
sprintf함수를 이용할 수 밖에 없다. 그러나
sprintf('A=B')
라는 코드는 실행창에 A=B를 표시하지만
A변수에 B값을 넣어주지 않는다. 그런데
eval(sprintf('A=B'))
라고 작성하면 'A=B'가 선언되며
실제로 A변수에 B값을 넣어주게 된다.


그러면 위 설명처럼 한번에
eval(sprintf('%s%g', 'handles.axes', i))
이런식으로 쓰면 되는데 왜
axesstr 변수에 sprintf 값을 넣고
axesh = eval(axesstr) 로 따로 선언했을까?


사실 이것 때문에 오류가 생기는 것을
못찾아서 한참을 고생한 적이 있었다.
eval함수 안에 또다른 함수가 들어갔을 때,
Matlab에서는 실행시 아무 문제가 없다.
하지만 컴파일 후 Matlab밖에서 실행을
하게되면 eval(sprintf(...)) 같은 경우
두 개의 함수가 충돌하게 되어 프로그램이
진행되지 않는다. 반드시 eval함수 안에
다른 함수를 넣는 것을 피해야 한다.


결국 쓰려고 했던 건
axes(handles.axes1); axis off;
를 for문에 넣기 위해 변형한 것이다.




다시 내용으로 돌아와서 다음 코드인
60~64줄은 첫번째 빌드 설명칸을 제외하고
전부 Visible 옵션을 off 하는 코드이다.
65~72줄은 첫번째 유닛수와 인구수를
제외하고 Visible 옵션을 off 하는 코드이다.
그러면 실행 시 첫번째 입력칸을 제외하고는
새로 추가하기 전까지 화면에 보이지 않는다.


이렇게 모든 객체 중 원하는 객체만
초기화면에 표시되도록 할 수 있다.




프로그램의 초기화면이다.
x0 (0/0) 글과 (input build exp...) 박스창이
첫번째를 제외하고 전부 보이지 않는다.


경우에 따라서는 Guide안에서 Fig파일의
속성을 직접 수정해서 초기조건을 정하는
경우도 있지만, 여러개의 객체를 한번에
설정하는 건 코드로 하는 것이 더 편하다.




다음으로는 프로그램 전반에 사용되는
전역변수의 선언이다. (76~86줄)


global 함수는 프로그램 전체에서
변수를 선언하고 불러오는 기능을 한다.
global 선언을 하지 않으면 동작 하나가
완료되고 나서 변수를 저장하지 않는다.


pro변수는 몇번째 axes까지 이미지가
추가되었는지 숫자로 저장하도록 했다.
num변수는 각 pro마다 유닛의 수가
얼마인지 저장하는 벡터 역할을 한다.
ppl변수는 (현재인구수/최대인구수)를
2열로 저장하는 행렬 역할을 한다.




90~96줄은 'Add'를 누르면 열리는
'uipanel' 안에 이미지를 추가하는 코드이다.
위쪽 코드와 같이 eval함수를 이용하여
sprintf함수로 폴더의 이미지를 순서대로
불러오게 되는데 imread와 'cdata' 속성을
이용해서 'pushbutton'에 이미지를 덮는다.


각주를 보면 알겠지만 다른 종족의
이미지도 똑같은 방법으로 불러오면 된다.




정상적으로 코드가 작성되면 'Add'버튼
클릭시 위처럼 이미지가 잘 덮여있다.


'pushbutton'의 태그 순서를 처음부터
잘 정렬해 놓았다면 for문을 이용하여
원하는 자리에 원하는 이미지를
쉽게 배치할 수 있다.


다음 포스팅에서는 'pushbutton'들의
Callback함수를 원하는 대로 코딩하는
방법에 대해서 알아보자.


프로그램을 다운로드 할 수 있는 링크가 폐쇄되어
현재는 프로그램을 다운로드 받을 수 없다