CafeM0ca

[JUCE]튜토리얼2 main component 본문

Programming/JUCE

[JUCE]튜토리얼2 main component

M0ca 2018. 2. 11. 17:29
반응형

//필요한것만 발번역 https://juce.com/doc/tutorial_main_component  

//모카 환경 우분투 16.04

콘텐츠 구성요소를 추가하는 방법을 배워보자. 자신의 창이 다른 그래픽 요소들을 포함할 수 있게


이 튜토리얼에서는 메인 콘텐츠 구성요소를 만들어내는것으로 어떻게 그래픽 콘텐츠를 어플리케이션 창에 추가하는지를 보여줄것이다. 



컴포넌트 클래스

모든 JUCE 그래픽 인터페이스에서 가장 중요한 기본 클래스는 Component 클래스다.(버튼,슬라이더,텍스트영역들이 컴포넌트)

기억할것: JUCE의 모든 그래픽 요소들은 Component 클래스로부터 파생된다. GUI를 빌다히기위해 다른 컴포넌트들은 서로 다른 구성요소가 상위 및 하위 컴포넌트가 있는 중첩 계층 구조로 정렬된다.

맨 위 컴포넌트는 메인 콘텐츠 컴포넌트로 불린다. 



메인 컴포넌트 클래스 추가하기

메인 컴포넌트 클래스를 만들어보자. 이 클래스에서 쓰일 소스코드를 새 파일로 만들자. Projucer에서 튜토리얼 프로젝트를 열자.

tutorial_main_component.zip



왼쪽에서 우클릭을 누르고 Add New Comonent class(split ...)을 선택하면 새 컴포넌트 서브클래스를 이름을 물을것이다.

MainComponent로 이름짓고 생성하자.


그러면 MainComponent.cpp와 .h파일 이 생성된다. 이제 프로젝트를 저장하고 자신의 IDE로 다시 열어라. 당신은 새 파일들을 볼 수 있을것이다.

Projucer는 자동적으로 코드를 생성해준다. 새 컴포넌트 클래스에. 이것은 다음 섹션에서 살펴보겠다. (저장은 컨트롤+s. 모듈때문에 저장 안된다고하면 경로문제니까 modules클릭해서 각각의 모듈들을 눌러서 global 뭐시기 체크 풀어주면 저장된다.)


IDE쓰는사람은 알아서하고 모카는 vim사용한다. 압축푼 파일의 소스로 들어가면 우리가 만든 파일들이 있다.



새 컴포넌트 클래스

컴포넌트 기본 클래스는 두개의 중요한 가상멤버함수를  가지고 있다. 이 가상멤버함수들은 모든 클래스에서 오버라이딩해야한다.

Component::pain(): 이 멤버함수는 정의한다 어떻게 당신의 컴포넌트가 스크린에 그려지는지, 그리고 반드시 구현되야한다. 모든 컴포넌트 클래스에서

Component::resized():이 멤버함수는 정의한다 크기를 조정할 때 컴포넌트가 어떻게 되어야하는지, 그리고 구현되어야한다 모든 컴포넌트 클래스에서(만약 이 컴포넌트가 절대로 당신의 앱에서 리사이즈되지 않는다면 예외다.)


Note: 항상 override키워드를 모든 함수에 추가해라 클래스 내부에서 그것은 기본클래스로부터 오버라이딩된다. 이것은 오류를 예방하고 JUCE의 코딩 표준이다.


paint함수 재정의하기

pain()함수는 정의된다 어떻게 컴포넌트 오브젝트가 스크린에 랜더링될지. 우리는 사용자 정의의 MainComponent클래스를 추가할거다.

Projucer가 자동적으로 데모 코드를 추가했놨다. pain()함수를 우리의 코드로 바꿔보자.

MainComponent.cpp파일에서 paint함수를 위와같이 수정해주자. 자세히 알 필요는 없고 내용상 fillAll은 가득 채우는 함수같고 setColour는 색상고르는 함수, 폰트는 사이즈같고 drawText함수는 첫번째인자로 메시지를, 두번째인자는범위, 세번째인자는 위치, 네번째인자는 활성화?같다.


이제 컴파일하여 코드를 실행해보자. 그러면 파란색 배경과 텍스트 대신에 비어있는 어플리케이션 창이 뜬다. 왜일까?

MainWindow 오브젝트에 대해 알아보자. 이것은 일부 콘텐츠를 보여준다. 우리는 헤더파일을 인클루드해야한다. 그래야 MainWindow가 MainComponent클래스를 알기때문이다. 

#include "MainComponent.h"

이것을 Main.cpp파일에 인클루드해주자. (원문에는 MainWindow.cpp라 되어있지만 Main.cpp에 MainWindow객체가 있으므로 Main.cpp에 인클루드 해주자.)

다음 단계는 MainComponent 객체를 만들어주고 main window의 콘텐츠로 추가해야한다. 우리는 그것을 DocumentWindow::setContentOwned()함수라 부른다.

Note: "Owned"는 MainWindow 객체가 이제 MainComponent 객체의 생존시간동안에 사용가능하다는걸 의미한다. 그리고 파괴된다 자동적으로 소멸자가 호출되면.


constructor의 MainWindow클래스의 생성자에 다음 줄을 추가해주자. (Main.cpp)

setContentOwned (new MainComponent(), true);

MainWindow 생성자는 다음과 같다.

Component::centreWithSize()함수는 자주 바뀐다. 우리는 이제 더 이상 MainWindow 객체의 크기를 명시적으로 설정하지 않지만 내용에 따라 크기를 파악하도록 지시한다.centreWithSize (getWidth(), getHeight());

그러나 이 작업을 수행하려면 MainComponent 객체가 centreWithSize()함수를 호출하기전에 크기가 설정되어 있어야한다.

만약 설정되지 않으면 main window는 window의 적당한 사이즈를 모른다. 다음 섹션에서 이를 수행하는 방법에 대해 설명한다.


변경된 Main.cpp의 MainWindow객체


컴포넌트 이즈 설정하기

Component객체의 사이즈를 설정하는 두가지 방법이 있다. 컴포넌트 자체의 생성자의 크기를 설정하던가 아니면 생성자의 부모 컴포넌트를 설정하던가.

main 컴포넌트의 경우, 우리는 보통 컴포넌트 자체를 설정한다. 다음 코드를 MainComponent클래스에 추가하자.

setSize (400, 300); //당연히 다른 크기도 된다.   

변경된 MainComponent.cpp

주의: 기억할것! 항상 당신의 컴포넌트를 설정할것. 이 단계를 생략하면 JUCE에서 버그가 매우 흔하게 발생한다.

MainComponent 객체의 사이즈는 inWindow 객체의 위치와 사이즈 지정하기전에 생성자에서 설정된다.


이제 필요한 조각들이 다 모였다. 다시 컴파일하고 실행해보면, 당신은 main 컴포넌트가 알맞게 어플리케이션 창을 그린것을 볼 수 있다.

(build->LinuxMakefile 디렉토리에서 make해주고 build로 가면 실행파일이 있다. 재차 말하지만 리눅스 기준이다. 다른 IDE는 알아서..)

MainWindow객체의 setCountentOwned() 함수의 두번째인자를 false로 바꿔주면 MainComponent의 setSize(400,300)이 적용되는것 같다.


resize함수 구현

paint()함수를 살펴봤다. 이제 MainComponent 클래스의 크기를 조정할 수 있는 방법을 살펴보겠다.


가장먼저 우리는 main window부터 볼 필요가 있다. 이것은 사이즈 조절할 수 있어야한다.  (모르겠으면 튜토리얼1 보고오면 된다.)


이제 컴파일하고 앱을 실행하면 window를 마우스를 사용해 리사이즈 할 수 있다. 당신은 MainComponent 객체가 main window 크기에 맞게 리사이즈된다. - 필요한 모든 코드가 이미 Component 기본 클래스에 구현되어있다.



그러나 구성 요소의 크기를 조정할 때마다 맞춤 작업을 수행하기를 원하면 어떻게해야할까? 아마 자식 컴포넌트가 main 컴포넌트 크기에 따라 다르게 레이아웃 해야할꺼다. 우리의 간단한 데모 앱을 보면 main 컴포넌트안의 텍스트를 현재 컴포넌트의 사이즈로 보이게 바꾸자.


완료하거나 업데이트해야하는 모든것이 우리가 리사이즈 해야할 때 컴포넌트는 컴포넌트의 resized()함수로 들어간다. 현재 함수는 비어있다. 기능을 추가해보자.


주의: Component::resized()함수는 자동적으로 컴포넌트의 사이즈가 변경되는 일이 발생할때마다 호출된다. 절대로 당신이 호출하지 말아라!


컴포넌트안에 표시되는 텍스트는 현제 리터럴(변하지 않는 값) 문자열 "Hello, World!"가 paint() 함수 안에 있다. 새 멤버 변수를 MainComponent 클래스 안에 도입하여 이를 바꿔보자.(네이밍에 신경쓰면서 변수 이름 짓기!) 

새 변수를 현재 main 컴포넌트 문자열의 크기로 말하길 원한다. 따라서 이걸 currentSizeAsString으로 부르겠다.


MainComponent.h



이제 currentSizeAsString이 우리가 원하는 대로 작동하게 구현하자. 2가지를 해야한다.

- currentSizeAsString의 컨텐츠가 스크린에 랜더링 되어야한다.

- currentSizeAsString가 메인 컴포넌트의 사이즈가 바뀌어도 스스로 업데이트 되어야한다. 

(텍스트를 화면 크기에 맞춰서 자동으로 사이즈 조절 해주는 것)


첫번째는 paint() 함수 내에서 g.drawText() 함수가 호출될때 간단하게  리터럴 문자열을 currentSizeAsString으로 바꾸면 된다.

두번째는 우리가 이미 매번 resized() 함수를 호출하는걸 알고 있다. 따라서 currentSizeAsString의 값을 업데이트해주면 된다.

void MainComponent::resized()
{
currentSizeAsString = String (getWidth()) + " x " + String (getHeight());
}

String 객체에 대한 것은 나중에 튜토리얼에서 배운다.


두번째는 currentSizeAsString변수를 페인트 함수로 채워서 수행한다.


MainComponent.cpp


Main.cpp



make로 빌드했다.

크기가 달라져도 글자가 정 중앙에 표시된다.


MainComponent.cpp에서 g.drawText의 첫번째 매개변수를 currentSizeAsString으로 바꿔주고 다시 빌드해보면


사이즈가 나온다. 


여기서 두 가지 흥미로운걸 관찰할 수 있었다. 첫번째로 자동적으로 디스플레이가 업데이트 되는 것. - paint() 함수가 호출되고 자동적으로 resized() 함수가 호출된다.

두번째로 앱이 시작될 때 크기가 올바르게 표시된다. 먼저 window를 직접 조정하기 전에 크기가 표시된다. 반드시 resized() 함수가 이미 호출되는걸 기억해라. 컴포넌트의 크기가 언제든 바뀔때마다. 처음으로 컴포넌트의 크기가 설정되고 앱이 시작된 후에 컴포넌트가 채워지는 경우를 포함한다.


연습하기

MainComponent::resize() 함수를 수정하여 언제든지 크기가 바뀔때 MainComponent 객체 또한 배경색이 바뀌도록 수정하시오.



컴포넌트(구성 요소 -> 텍스트 라던가)를 추가하고 paint() 함수와 resized() 함수를 구현해봤다. 

주의: Component::resized()함수는 자동적으로 컴포넌트의 사이즈가 변경되는 일이 발생할때마다 호출된다. 절대로 당신이 호출하지 말아라!

꼭 명심하자.



반응형
Comments