JavaFX 응용 프로그램 기본 코드

JavaFX의 기본 코드는 AWT와 Swing과는 상당히 다르다. 어떤 패키지의 어떤 클래스를 이용하여 응용 프로그램을 만들 것인가, 우선 기본적인 부분을 살펴 보자.

JavaFX란 무엇인가?

오랫동안 기다려야 했던 Java 8이 등장하고 잠시 경과되었지만, 이 새 버전에 익숙해져 있는가? Java 8에서는 다양한 새로운 기능이 추가되어 있지만, 그 중에서도 Java에 큰 개혁이라고 하면 “Swing에서 JavaFX로 전환"것이다.

지금까지 Java에서 데스크톱 응용 프로그램을 개발할 때 GUI 라이브러리로 사용되어 온 것은 “AWT"와과 “Swing"이었다. 그렇다고 해도, AWT는 GUI를 기본으로 준비되어 있을뿐, 실제로 활용되고 있던 것은 그것을 기반으로 구축된 Swing이었다고 해도 과언이 아니다. Swing는 오랫동안 일반 Java GUI로 널리 사용되고 왔다.

하지만 Java8이 되고, 새로운 ‘JavaFX’가 기본으로 장착되어 Swing에서 JavaFX로 전환이 확정되었다. 물론 당장은 Swing도 공존하기 때문에 빨리 없어지는 것은 아니지만, 어느 Swing가 중지된 JavaFX로 일원화하는 것은 거의 결정된거 같다. (이것은 현재 Java 개발을 다루는 오라클의 Web 사이트에 명시되어 있다. http://www.oracle.com/technetwork/java/javafx/overview/faq-1446554.html#6” Is JavaFX replacing Swing as the new client UI library for Java SE?”)

그럼, 이 JavaFX이라고 하는 것은 어떤 것인가?

오랫동안 Swing을 이용하여 온 많은 사람들은 “어차피 AWT와 Swing을 기반으로 개량한 것일까? 조금 살펴보면 바로 사용할 수 있게 되겠지"라고 생각하는 사람도 많을지도 모른다. Swing가 등장했을 때, 내용 적으로는 아주 새로워 졌어도, 이벤트 시스템과 그래픽 렌더링 시스템 등 기본적인 구조는 AWT를 그대로 계승되었기 때문에, 그만큼 혼란은 일어나지 않았다 . 물론, 새로운 GUI가 많이 추가되었다기 때문에 AWT와는 전혀 달랐지만, 그래도 근본 개념부터 다시 이해해야 할 필요는 없었다. Swing는 ‘개혁’이나 ‘혁명’는 없었던 거다.

하지만 JavaFX는 다르다. 이것은 ‘혁명’이다. 기존의 AWT/Swing의 개념은 마치 통용되지 않는다. Button이나 TextField 등 예전 클래스 이름은 그대로 계승되고 있지만, 그것을 통합하는 Stage 같은 건 본 적도 없는 클래스이기도 하다 (실은 Button와 TextField도 실제로 XML 코드로 작성하기도 한다). 우선 Frame 클래스를 상속(?)하지 않는다 (그런 클래스가 없다). 이벤트 리스너를 통한 이벤트 처리(?) 같은 것도 사용하지 않다 (있지만). paint 메소드와 Graphcs 그래픽 그리는(?) 메소드도 클래스도 없다.

JavaFX는 AWT/Swing의 기본적인 GUI 시스템과는 전혀 다른, 완전히 다른 체계이다. 그 점을 확실히 기억하도록 하자.

Application클래스의 기본코드

그럼, JavaFX 응용 프로그램은 어떻게 만드는지 그 기본을 살펴 보자. 앞에서 “GUI 근본이 다르다"고 위협(?)하여, “어떻게 프로그램 만드지?“라고 불안해 하는 사람도 있을지 모르겠다. 하지만 그렇게 걱정하지 않아도 된다.

응용 프로그램의 기본은 Java의 기본대로 “main 메소드"를 구현한 클래스를 작성하고 이를 실행하는 것뿐이다. 일반적인 Java 클래스를 작성하면, JavaFX 응용 프로그램을 만들 수 있다는 것이다. 이 점에 대해서는 어떠한 변화도 없다.

다만, JavaFX 응용 프로그램의 클래스는 ‘Application’이라는 낯선 클래스를 상속하여 만들어야 한다.

아래와 같이 응용 프로그램에는 가장 기본적인 형태를 기억해 두자. 이것이 JavaFX 응용 프로그램의 기본이다.

public class 클래스 extends Application {
 
    public static void main(String[] args) {...}
 
    @Override
    public void start(Stage stage) throws Exception {...}
 
}

JavaFX 라이브러리는 “javafx"라는 패키지에 포함되어 있다. 응용 프로그램은 javafx.application 패키지에 있는 Application이라는 클래스를 상속받는다. 이 클래스는 추상 클래스이며, “start"라는 메소드가 포함되어 있어 반드시 이것을 구현해야 한다.

이 start 메소드는 응용 프로그램이 시작 할 때의 처리를 만들기 위한 것이다. 이 메소드는 javafx.stage 패키지의 Stage라는 클래스의 인스턴스가 인수로 전달된다. 이 Stage는 “최상위 컨테이너"이라는 것으로, GUI 기본 토대가 되는 컨테이너이다. AWT/Swing에서는 Frame과 JFrame 같은 클래스에서 윈도우를 만들고 표시 했지만, JavaFX의 경우 이 Stage를 사용하여 윈도우를 구축하는 것이 기본이다.

Swing 등과 달리 JavaFX에서는 “GUI를 통합하는 윈도우 본체는 JavaFX 측에서 준비되어 있다"는 점이다. Stage를 상속한 클래스를 준비하여 인스턴스를 만드는 것도 아니고, 응용 프로그램을 시작하면 처음에 표시되는 응용 프로그램의 윈도우로 Stage 인스턴스가 start에 전달된다. 프로그래머는 단지 그 전달된 Stage를 이용하여 GUI를 구축할 뿐이다.

응용 프로그램을 만들어 보자

그러면 실제로 간단한 응용 프로그램을 만들어 움직여 보자. 아래와 같이 샘플 코드를 작성해 보겠다.

package com.devkuma.javafx;
 
import javafx.application.Application;
import javafx.stage.Stage;
 
public class App extends Application {
 
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage stage) throws Exception {
        stage.show();
    }
 
}

여기에서는 com.devkuma.javafx 패키지에 “App"라는 이름으로 클래스를 작성하였다. 필요에 따라 패키지와 클래스 이름은 작성하면 된다.

이것을 실행해보면 아무것도 없는 하얀 창이 화면에 나타난다. 닫기 버튼을 클릭하여 닫으면 응용 프로그램이 종료된다. 극히 간단한 처리이다. 그럼, 여기서 행하고 있는 것들을 정리해 보겠다.

launth 메소드

우선 main 메소드에서는 Application 클래스에 포함되어 있는 “launch"라는 메소드를 호출한다. 이것은 클래스 main 메소드에 인수로 넘어온 String 배열을 그대로 인수로 넘겨서 JavaFX 응용 프로그램을 시작한다. “JavaFX 응용 프로그램의 시작은 launch"라는 것을 기억하자.

show 메소드

start 메소드에서는 인자로 전달된 Stage 인스턴스의 “show"메소드를 호출한다. 이것은 그 Stage에서 구축된 윈도우를 화면에 표시하는 것이다. 반대로 윈도우를 숨기는 hide라는 메소드도 포함되어 있다.

Swing을 사용했던 프로그래머라면 윈도우의 표시 show/hide를 사용한다는 것에 대해서 거부감이 있을 지도 모른다. 지금까지 “show/hide이 아닌, setVisible를 계속 사용했을 것이기 때문일거다. 하지만 Stage에는 setVisible는 없다는 것을 기억하자.

Scene, Pane 및 구성 요소

그럼, 이 창에 간단한 구성 요소를 추가하자. 가장 간단한 것으로, 텍스트를 표시만 하는 요소를 추가하여 보기로 하자.

아래에 소스 코드가 그 예이다.

package com.devkuma.javafx;
 
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
 
public class App extends Application {
 
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage stage) throws Exception {
        Label label = new Label("This is JavaFX!");
        BorderPane pane = new BorderPane();
        pane.setCenter(label);
        Scene scene = new Scene(pane, 320, 240);
        stage.setScene(scene);
        stage.show();
    }
 
}

이것을 실행하면 윈도우 중앙에 “This is JavaFX!“라는 텍스트가 표시된다.

텍스트의 표시는, AWT/Swing과 마찬가지로 “Label"이라는 클래스가 포함되어 있다. 이것은 SWT/Swing의 “Label"과는 다르다. javafx.scene.control 패키지에 포함되어 있는 JavaFX 전용이다.

이것으로 텍스트를 표시가능 하지만, 그러나 단순히 Stage에 Label을 추가할 수 있는가? 그러지는 않는다. Stage에는 “Scene"과 “Pane"이라는 것을 사용하지 않으면 안된다.

Scene이란?

“Scene"이라는 것은 Stage에 포함되어 있지만 보이지 않는 컨테이너이다. Stage는 윈도우이지만,이 창에 표시되는 내용을 구축하는 것이 Scene이다. 이 Scene에 포함된 것을 Stage에 집어넣어 표시하는 것이다. 이 Scene은 다음과 같은 형태로 인스턴스를 생성한다.

new Scene(Pane, , 높이);

폭과 높이는 알고 있듯이 생성할 컨테이너의 크기이다. 이를 Stage에 집어넣는 것으로, 그 크기에 윈도우가 조정된다.

그럼 Pane이란? 구성 요소 종류를 포함 토대가 되는 컨테이너이다. Scene은 Pane을 하나만 포함 할 수 있도록 되어있다.

Pane은 1개만 있는 것이 아니라 여러 가지 종류가 있다. Pane안에서 어떠한 구성 요소를 포함되어 있는가에 따라 레이아웃 방식이 달라진다. AWT/Swing이라고 한다면 “레이아웃 매니저"와 같은 것이다. 다만, 레이아웃 관리만하는 레이아웃 매니저와 달리 Pane은 “컨테이너에 레이아웃 매니저 기능이 내장된 것"이라고 생각하면 좋을 것이다.

정리하면 구성 요소를 사용하는 윈도우의 구성은 다음과 같다.

  • Stage에서 Scene이 포함되어 있다.
  • Scene에 Pane이 포함되어 있다.
  • Pane에서 구성 요소가 포함되어 있다.

이것으로 겨우 구성 요소 종류를 사용할 수 있게 되는 것이다. 조금 구조는 다르지만, Swing 등 컨테이너를 조합하여 화면을 만들었으니 그만큼 위화감은 없을 것이다.

BorderPane

Pane은 여러 종류가 있다고 말했었다. 앞에 예제에서는 BorderPane라는 Pane을 사용했었다. 이것은 BorderLayout 내장 된 컨테이너라고 생각하면 좋을 것이다.

이 BorderPane는 new BordrePane()와 같이 인수없이 인스턴스를 만든다. 구성 요소의 기본 메서드를 호출하여 추가한다.

중앙에 위치

*BorderPane*.addCenter(구성 요소);

상단에 위치

*BorderPane*.addTop(구성 요소);

하단에 위치

*BorderPane*.addBottom(구성 요소);

오른쪽에 위치

*BorderPane*.addRight(구성 요소);

왼쪽에 위치

*BorderPane*.addLeft(구성 요소);

이것으로 상하 좌우 중앙의 5개 구성 요소를 위치시킬 수 있다. 아무튼, 감각적으로는 BorderLayout과 같기 때문에 쉽게 알 수 있을 거다.

FlowPane

이 외에도 Pane은 여러가지가 준비되어 있다. 그 중 한개가 FlowPane라는 것인데, 이것은 FlowLayout 와 같은 것으로, 추가 구성 요소를 순서대로 정렬하여 표시하는 것이다.

new FlowPane();

이와 같이 인수없이 인스턴스를 생성한다. 레이아웃의 구조 등은 FlowLayout과 동일하지만, 그러나 포한된 구성 요소의 관리는 조금 다르다.

FlowPane 내부에서는 포함된 구성 요소 종류를 List에 함께 관리하고 있다. 이 List 인스턴스는 getChildren라는 메소드로 꺼낼 수 있다. 이 List에 구성 요소를 추가하여 표시되도록 한다. 아래를 보면,

pane.getChildren().add(label);

이런 방식으로 하여 구성 요소를 추가하고 있다는 것을 알수 있을 거다. 뭔가 불편하게 생각하는 사람이 많을 지도 모르지만, “List로 관리한다"는 것은 컨테이너 내의 구성 요소를 다루기 위해 특별한 방법이라고 기억하지 않길 바란다. 보통의 컬렉션과는 다른 것이다.

우선, BorderPaneFlowPane을 익히면 구성 요소 기본적인 빌트인을 사용할 수 있게 된다. 그 외에 Pane은 조만간에 다시 다루기로 하자.

package com.devkuma.javafx;
 
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
 
public class App extends Application {
 
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage stage) throws Exception {
        Label label = new Label("This is JavaFX!");
        FlowPane pane = new FlowPane();
        pane.getChildren().add(label);
        Scene scene = new Scene(pane, 320, 240);
        stage.setScene(scene);
        stage.show();
    }
 
}



최종 수정 : 2017-09-19