2012년 7월 22일 일요일

스윙으로 레이어 만들기(JLayeredPane)

혹시 여러분은 자바의 마스코트가 무엇인지 아는가?
모르겠다면 여기를 보시라~ 쨔잔~


자바(Java)의 공식 마스코트인 듀크(Duke)를 소개합니다당.


크흐 역시 자바의 마스코트에 걸맞게 공부를 하고 있군요.^^

듀크는 오래전 썬마이크로시스템스사에서 자바를 개발할 당시에 그린 프로젝트팀(Green Project Team)의 첫작품 스타7(Star7)이라는 홈 엔터테인먼트 기기의 유저인터페이스에 삽입된 만화캐릭터가 있는데 그게 바로 지금 소개한 듀크다. 당시 팀의 그래픽을 담당했던 멤버로서 듀크를 디자인한 조 팔랑(Joe Palrang)은 지금은 너무나도 유명한 애니메이션 영화 "슈렉"으로 널리 알려진 그래픽 아티스트다. 이런 듀크는 2006년 자바 테크놀로지의 공식 마스코트로 세상에 널리 알려지게 되면서 대표적인 오픈소스 시대의 아이콘으로 자리잡았다.

필자가 갑자기 강의는 하다말고 도대체 왜 듀크를 소개하느냐고 부글부글 학구열에 불타오르는 이가 혹시 있을지도 모르겠는데 만약 만에 하나 혹시라도 만명중에 한명이라도 있다면 진정하라. 그건 다름아닌 필자의 강의에 JLayeredPane 특별게스트로 듀크가 등장하기 때문이다.ㅎㅎ

지금부터 잠시 숨은 그림 찾기를 시작해 보겠다. 아래의 두 그림을 보면서 듀크가 어느 판떼기(?) 선상에 있는지 대답해보기 바란다.^^



자 위의 두 그림에 듀크가 여러분에게 손을 흔들고 있다. 듀크는 어느 판떼기 선상에 있는가? 첫번째 그림부터 보면 처음은 Yellow (0) 판떼기랑 같은 레벨에서 손을 흔들고 있고 두번째 다음 그림에는 Cyan (2) 판떼기랑 동일 선상에서 손을 흔들고 있다. 그림의 상단부분을 보면 이미 해답이 나와있는 것을 알수 있을 것이다. 여기서 필자가 진정 말하고자 하는 부분은 이렇게 판떼기를 겹겹히 쌓아놓은 것만으로도 입체감있게 화면구성이 가능하다는 점이다. 이런 구성은 여러분이 평소 알게 모르게 접하고 있는 프로그램들의 메뉴바나 툴바같은 화면을 상상하면 이해가 쉬울 것이다. 그림을 보면 듀크가 빨간 판떼기 뒤에서 손을 흔들고 있는것처럼 보이지 않는가? 바로 이렇게 원근감 있게 화면을 구성가능하도록 만들어주는 스윙 클래스가 바로 오늘 배울 JLayeredPane 되시겠다.ㅎㅎ

서론이 길었다만 자바 3D(3rd Dimension) 세계를 몸소 체험할수 있는 강의가 이제부터 전개된다. 그 이름하여 JLayeredPane 되시겠다. 자 영어가 약한 이들은 단어부터 찾아본다. layer랑 pane이 무엇인지를 말이다. 대충 감이 올텐데 간단하게 필자가 그냥 못박아서 말해주겠다. 층층이 쌓아놓은 판떼기로 해석하면 되겠다.ㅎㅎ

자바코드가 어쨌거나 영어로 만들어야되다보니 layer나 pane같은 용어가 나오면 말그대로 레이어 때문에 폐인이 되는듯한 금단현상(?)이 올지도 모르겠다. 여러분은 오늘 아마 시간이 지나면 지날수록 온몸의 사지가 마비되고 경직되어 심한 정보로 인한 심부전 및 심장마비등 호흡중추를 마비시키는 강한 부작용이 일어날수 있으나 그것은 모두 필자의 강의에서 비롯되는 엄청난 희열로 촉발된 엔돌핀에 유발되는 반응이기 때문에 안심해도 된다. 오늘 강의가 그 정도의 폭발력을 가진 강좌이기 때문에 그런 현상은 지극히도 당연한 것이다.ㅎㅎ 그러니 본 강의에 졸지말고 눈좀 뜨란 말여~ 껄껄 강좌가 진행될수록 필자의 농(?)만 들어가는구나.ㅎㅎ

다시 돌아가서 위의 그림들을 보면 칼라 옆에 괄호로 숫자들이 적혀있을 것이다. 그게 무엇을 표시한거냐면 깊이(depth)다. 수치가 높을수록 점점더 층이, 레이어가 높아진다고 생각하면 쉽게 이해가 될것이다. 한마디로 위판떼기부터 아래판떼기까지의 깊이라 생각하면 된다. 유식한말로 Z order 젯 오더다. 오케? ^^

그럼 언제나처럼 이제 필자가 한타 한타 하루가 일년같이 정성에 정성을 쏟아부은 명품(名品) 예제를 보는 시간을 갖겠다. 항상 그렇지만 이상하리만치 예제만 보아도 술술 이해되는 놀라운 경험을 하게 될것이다. 단 그를 위해선 한가지 조건이 있다. 타자좀 쳐라~ 그냥 눈으로 보지만 말고~~ 난 다 알고있다. 그(?)가 누군지. -.-; ㅎㅎ 그럼 어떤걸 만드는지 결과부터 보고 소스를 보기로 하자.




총 다섯장의 판떼기를 만들었다. 어떻게 이렇게 판떼기를 겹겹히 쌓아놓은 것처럼 보이게 만들수 있을까? 다시 말해서 JLayeredPane 클래스를 어떻게 써야 이렇게 입체감이 나게 만들수 있을까?  여러분은 오늘 강좌를 통해서 이제 자바로 3D(?)를 구현할수 있게 된다. 개봉박두~ ㅎㅎ 그럼 소스를 보자.



소스가 좀 길어서 그런지 눈이 침침하다 하는 이들은 클릭혀라. ㅎㅎ 소스가 길어보이나 여러분이 오늘 알아야할 내용은 단지 아래의 여섯줄에 불과하다.

JLayeredPane jlp=frame.getLayeredPane( );

jlp.add(one,new Integer(0));
jlp.add(two,new Integer(100));
jlp.add(three,new Integer(200));
jlp.add(four,new Integer(300));
jlp.add(five,new Integer(400));

그래도 설명을 덧붙이자면 프레임을 만들고 판떼기를 간단하게 버튼으로 만들었다. 이미 JButton에 대해서 배웠으니 코드보고 이 정도는 손쉽게 진행가능하리라 생각한다. 그리고 오늘 배우려는 JLayeredPane에 대해서 덧붙이면 끝난다. 여기서도 조금 더 덧붙이자면 버튼만들때 setBackground( )랑 setBounds( ) 메소드는 어디서 튀어나온거야 하는 이들은 없겠징? 이미 써보기도 했을 것이고 이제 이런건 스스로 깨우칠때가 되었지만 다시 설명하자면 JButton에 대해서 곰곰히 들춰보면 대부분의 스윙 클래스가 그렇듯이 기존의 awt 콤포넌트(Component)와 컨테이너(Container) 내용을 다 쓸수 있도록 계승하고 있다. 이런 메소드들은 콤포넌트의 일종이므로 별다른 제약없이 필요하면 이렇게 그래픽 요소들을 편하게 쓸수 있도록 자바에서 배려해놓은 것이니 잘만 활용하면 될것이다. 말한김에 컨테이너는 콤포넌트를 보강하기 위해 만들어놓은 것이라 생각해도 무방하다. 그리고 이런 것들을 스윙에서는 JComponent에서 계승하고 있다. 사실 이런건 자바 클래스 족보를 열심히 보면 자연스레 습득되는 것이니 이거 또 외운다고 그러지는 말아라. 족보도 필자가 초반에 보여줬을텐데 언젠가 써먹게될꺼라고 말이다.ㅎㅎ

자 사설 그만접고 다시 강의로 돌아가서 보면 setBackgound( )는 한마디로 판떼기 색깔 정하자는 것이고 setBounds( )는 판떼기 위치랑 사이즈 정하자는 것이다. 이건 예전 시간에 했으니 따로 설명하지 않겠다. 자 그럼 본격적으로 오늘의 핵심인 위의 코드 여섯줄을 분석해 보자.

JLayeredPane jlp=frame.getLayeredPane( );

말그대로 JLayeredPane 쓰려고 jlp라는 인스턴스를 만들었다. 오른편은 지금 이 프레임에 레이어페인 쓰기위해 가져오자는 것이다. JApplet, JDialog, JFrame, JInternalFrame, JRootPane, JWindow, RootPaneContainer 같은 클래스에서는  이런 레이어 페인을 자동으로 쓸수 있게끔 되어있으므로 그냥 가져와서 편하게 쓰면 된다. 그리고나서 소스처럼 JLayeredPane에다가 add( ) 메소드를 이용해서 각 판떼기에 깊이를 Integer를 이용해서 수치를 지정하면 수치에 따라 화면에 판떼기가 층층이 쌓이는 것이다.ㅎㅎ 물론 수치는 아무거나 바꿔도 된다. 수치 바꿔가면서 어떻게 판떼기 배치가 바뀌는지 관찰하면서 공부하기 바란다. 필자가 수치를 이렇게 적어놓은것도 판떼기를 다섯장 만든것도 다 이유가 있는데 그 이유는 좀더 읽어보면 필자의 아낌없이 퍼주는 세심한 배려에 여러분의 마음은 장작불을 때듯 뜨겁게 타오를 것이다.^^

잠깐, 아직 안 끝났다.ㅎㅎ 밑에 보면 코드 다섯줄 생략해 놓은 부분이 있는데 이것을 이제부터 설명하겠다. 정확히 위의 다섯줄과 대체가 가능한데 아래의 그림 한장을 보면 특별한 설명없이도 저절로 이해가 될것이다.^^


자바에서는 판떼기를 편하게 배치하라고 이렇게 이름을 만들어 놓았다.

한마디로
DEFAULT_LAYER랑 new Integer(0)랑 같고
PALETTE_LAYER랑 new Integer(100)랑 같고
MODAL_LAYER랑 new Integer(200)랑 같고
POPUP_LAYER랑 new Integer(300)랑 같고
DRAG_LAYER랑 new Integer(400)랑 같다.

일반적으로 레이어를 놓으면 DEFAULT_LAYER 깊이로 정해진다고 생각하면 된다. 그리고 사실 디폴트 레이어 밑에 FRAME_CONTENT_LAYER 즉 new Integer(-30000)에 해당하는 레벨의 레이어가 있는데 잘은 쓰지 않으므로 일단 참고로 있다고만 알아두기 바란다. 이런 명령어들은 편하게 쓰라고 자바에서 배려해놓은 코드인데 이 내용을 몰라서 저건 또 뭐지뭐지하는 이들이 많은데 오늘 강이의 자바 강좌를 정독한 이들은 이제 이런 늪에서 빠져나오기 바란다.^^ 그동안 스윙 강좌만 계속 진행하니 다른 논리 강좌 좀 해달라고 물밀듯이 밀려오는 성화에 필자는 여러분의 요청을 급겸허히 받아들여 다음 시간에 스윙에 관련된 강좌를 마지막으로 진행하고 다른 부분을 건드리기로 심사숙고해서 결정을 내렸다. 필자가 중대한 결정을 내린만큼 남은 마지막 시간까지 최선을 다해 강의에 임해주기 바란다. 이상은 원래 예정된 강좌 수순이므로 어차피 다음이 마지막 스윙 강좌인 것을 강조할겸해서 급과장을 한것임을 특별히 알리는 바이다. 장문의 글을 읽느라 수고 많았다. 모두 냉수나 한잔 마시자~ㅎㅎ

2012년 6월 17일 일요일

스윙으로 내부프레임 만들기(JInternalFrame)


Special-Purpose Containers
JInternalFrame
JLayeredPane
Root pane(JRootPane)


오늘부터는 UI에서 특정한 목적을 수행하기 위해 쓰이는 콤포넌츠에 대해서 공부해 보기로 하겠다. 위의 총 3가지 콤포넌트들을 살펴볼텐데 각각의 컨테이너들이 어떻게 쓰이는지 각 요소별로 필자의 예제와 곁들인 학습을 통해 여러분의 사고력을 증진시키는데 중요한 시간이 되리라 기대하면서 순서대로 오늘부터 학습하겠다. 그럼 오늘은 JInternalFrame에 대해서 알아보면서 슬슬 시작해보자.^^


JInternalFrame의 단어에서 풍기는 의미를 분석해보자. J로 시작하니 자바스윙이고 Internal이라고 하니 뭔가 안에 있는 것이고 Frame이라고 하니 프레임인가 보다. 그러니 자바스윙으로 내부프레임을 지칭하고 있는 함축적인 의미가 영어단어만 봐도 머리속에 팍팍오고 있을 것이라 기대하면서도 깊은 의심이 맴돌고 반신반의하는 마음이 교차하고 있지만 필자는 여러분을 굳게 믿고 묵묵히 강의를 진행해 보겠다.ㅎㅎ




오늘 공부하게될 예제의 결과물을 여러분의 흥미를 돋구기 위해 미리 공개하였다. 위의 그림에서 보다시피 가장 바깥에 항상 있는 기존 프레임 안을 보면 총 5가지의 내부프레임이 보일 것이다. 이 5가지의 내부프레임을 통해 여러분은 내부프레임으로 구성할수 있는 5가지 핵심기능들의 정수들을 바로 오늘 이시간 필자의 예제를 통해 짜릿한 흥분과 엄청난 경외심을 느끼면서 공부하게 될것이라 내심 흠칫 기대해 보면서 슬슬 이야기 보따리를 풀어보겠다.^^

예제코드를 보기에 앞서 여러분의 이해도를 높이기 위해 JInternalFrame을 쓸때 항상 염두에 두면서 프로그램을 짜야하는 사항이 있는데 그중에서 가장 기본적인 사항들을 간략하게 설명하자면 첫째로 내부프레임을 쓰기위해서 컨테이너에 집어넣어야 하고, 둘째로 사이즈를 지정해야하고, 셋째로 위치를 지정해야하고, 넷째 마지막으로 이것을 보이게끔 설정해 주어야한다.

지금 저게 무슨 말이지 정신이 멍한 이들이 있다면 그것은 너무도 당연한 것이다. 배우지도 않았는데 어떻게 벌써 다 이해한단 말인가? 원래 강의란 것이 좀 어렵다싶은 화두를 던져놔야 그게 나중에 그럴듯해 보인다.ㅎㅎ

자 설명 들어간다. 내부프레임을 만들려고 하는데 그럼 당연히 어느정도 크기로 만들어야지하는 기본적인 질문이 생길것이다. 그리고 프레임안에 넣으니 어디에 표시를 해야될지 생각하게 될거고 내부프레임 기본 설정이 자바에서는 기존 프레임처럼 원래 보이지 않게끔 되어있다. 따라서 이것을 보이게끔 바꿔줘야 써먹을수가 있도록 자바에서 만들어 놨으니 그냥 보이게끔 설정하는 방법만 알면된다. 너무 당연한걸 풀어서 설명하니까 어이가 없을 것이다. 이제 이 당연한 것을 예제코드로 보면서 여러분이 궁금해할만한 포인트만 콕콕 찝어서 풀어내도록 하겠다.^^


필자가 내부프레임에 대해서 핵심만 공부할수 있도록 정성에 정성을 담았으니 여러분은 온 힘을 기울여 필자의 정성을 쪽쪽 빨아가야 할것이다. 자 그럼 예제를 분석해 보도록 하자. 여러분이 위의 클래스 불러들인 것을 보면서 내부프레임 클래스 말고 JDesktopPane이라고 하는 생소한 클래스가 하나 보일 것이다. 아까 필자가 컨테이너에 넣어서 내부프레임을 만들어야 보인다고 했는데 보통 이 클래스에다가 내부프레임을 넣어서 보이도록 만든다.

JDesktopPane은 JInternalFrame의 부모격으로 쓰인다고 생각하면서 이용하면 이해가 쉬울 것이다. 또한 JDesktopPane에서 기본적으로 유저인터페이스의 자바 룩앤필이 적용되어 있으니 내부프레임이 조금 그럴듯하게 기존 윈도우 프레임보다 멋있게 나온다.

다시 프로그램으로 돌아가서 보면 이 예제의 핵심 부분은 바로 Enhanced For Loop 안에 있는 것이 지금 공부해야될 내부프레임의 요체라 할수 있겠다. 사실 포룹 위아래에 있는 것은 여태껏 지겹게 보아왔을 것이므로 설명 생략하고 본론으로 들어갸겠다. 그리고 향상된 포룹 형태인 enhanced for loop에 대해서 까먹었다면 필자가 예전에 강의했던 for loop 강좌를 다시 한번 숙지하고 이 자리로 돌아와서 보기 바란다. 필자 리바이벌은 안한다.ㅎㅎ

왜 필자는 For 룹을 굳이 이용했을까? 이런 의문이 드는가? 그럼 다시 한번 예제의 결과물을 쳐다보기 바란다. 내부프레임을 5개 만들려고 한다. 프레임이 다 비슷비슷하다. 그림처럼 코드도 거의 비슷한 것이 5번이나 반복될 것인데 이것을 왜 5배나 힘들게 생고생해야하나? 배운 것은 써먹자. 제발, 아끼지 말고~ ㅎㅎ

public JInternalFrame(String title,
                      boolean resizable,
                      boolean closable,
                      boolean maximizable,
                      boolean iconifiable)

지금 위의 코드는 바로 JInternalFrame의 생성자 중 하나인데 필자의 예제에 있는 internalFramesArray가 바로 이를 기초로 하고 있다. 첫째 매개변수는 제목을 쓰는데고, 두번째는 프레임에다가 마우스 갖다대면 화살표로 바뀌면서 폈다 줄였다 하는 기능이고, 세번째는 창을 닫게 하는 기능, 네번째는 보통 프레임 오른쪽 상단에 보면 중간에 있는 버튼으로 화면 확대와 줄임 기능이고, 다섯번째는 보통 프레임 첫번째에 위치하는 버튼으로 화면을 최소화할때 사용하는 기능을 말하는데 이게 boolean이다. 따라서 true나 false로 가능하게 만들지 아니면 사용하지 못하게 할지의 여부를 결정할수 있는 것이다. 예제의 배열에서 필자가 false를 각 요소마다 하나씩 넣은 이유가 이런 기능들을 프로그램을 구동시키면서 살펴보라고 고려한 끝없는 배려심이 담겨있는 것이니 그점 생각하면서 직접 버튼을 눌러보면서 차이점을 알아보는 시간을 필히 갖기 바란다.^^

그리고 필자가 예제의 핵심부분이라고 말했던 for 룹은 실상 가르칠게 없다. 여러분은 이미 알게모르게 내부프레임의 정수를 깨우치고 있을 것이기 때문이다. 필자가 내부프레임을 만들때 염두에 두어야 하는 사항 네가지를 이미 알려주었다. 그 네가지 사항이 바로 for 룹안에 있는 네단락에서 펼쳐지고 있는 것이다. 내부프레임을 어떻게 만드는지 프로그램의 흐름을 이미 알고있다면 그냥 보기만해도 저절로 이해가 될것이다. 굳이 들어가자면 사이즈와 크기를 지정하는 방법이 궁금할텐데 필자가 이미 그건 주석을 달아 한큐에 해결해 버렸으니 더 설명할 것도 없을 것이나 그래도 궁금해하는 이들이 혹여나 있을까봐 조금만 더더 설명하겠다.ㅎㅎ

사이즈와 크기를 한큐로 해결하는 방법이 콤포넌트에 있는 setBounds( )라는 메소드를 이용하는 방법이다. 물론 setSize나 setLocation같은 메소드를 이용할수도 있겠으나 좋은 길 놔두고 굳이 돌아갈 필요는 없다하겠다.

public void setBounds(int x, int y, int width, int height)

바로 위의 코드인데 x랑 y는 중심 좌표로 위치를 찍을수 있고 width랑 height을 통해 프레임의 가로와 세로 사이즈를 정할수 있다. 그리고 CENTER가 들어가 있는 것들은 원하는 곳에 위치를 설정해 주는 것인데 프레임을 최소화하거나 최대화시켰을때 내부프레임이 제대로 표시되도록 해주기위한 장치이다. 이게 말로 설명하는 것보다 이거 없애버리고 직접 실행해보면 저절로 알게된다. 마지막으로 setVisible( ) 메소드를 통해 보이게끔 만들어주는데 기존 프레임처럼 내부프레임도 이것이 있어야 볼수 있음을 잊지 말기 바란다. 한마디로 내부프레임을 만들면서 기본적으로 고려해야할 사항 네가지를 여러분이 숙지한다면 거침이 없을 것이다.^^