티스토리 뷰
안녕하세요 박스여우입니다. 이번에는 JavaFX를 이용하여 가장 기본적인 버튼 클릭 이벤트를 구현해보도록 하겠습니다.
■ FXML & Controller
지난 포스팅때도 말씀드렸다 싶이 JavaFX는 MVC 패턴을 사용하여 View를 FXML과 CSS로, 컨트롤러는 전달된 UI 컴포넌트를 의존성 주입 방식으로 활용하게 됩니다. 따라서 UI를 디자인 하는 디자이너와 프로그램을 개발하는 개발자 사이의 일을 명확하게 구별할 수 있습니다.
이번에는 이런 JavaFX의 기능들을 활용하여 FXML로 UI를 구현하고, 그 UI를 Controller로 다뤄보도록 하겠습니다.
■무작정 따라해보기
지난 포스팅에서 진행한 eclipse에서의 JavaFX 셋팅을 진행해 주셔야 이번 과정을 수행하실 수 있습니다.
eclipse에서 New Project > JavaFX > JavaFX project 를 선택
프로젝트의 이름을 정하고 생성을 완료하셨다면 이제 클래스를 만드는것과 같이 패키지를 우클릭 한 뒤에 New > Other...을 선택해 주세요
다음으로 New FXML Document를 선택해 주시고 fxml의 이름을 설정해 주세요. 저는 main.fxml로 진행하겠습니다. 이름이 굳이 같을필요는 없지만 해당 포스팅을 따라하시기에 번거로우실 수 있습니다.
그러면 위와 같이 main.fxml이 생성됩니다. fxml은 Android를 해보셨다면 아시겠지만 android의 UI를 구성하는 xml과 매우 유사하다는 것을 볼 수 있을것입니다. 따라서 xml을 다뤄본적이 있으시다면 fxml을 한결 더 수월하게 작성하실 수 입습니다.
이제 main.fxml에 main gui를 구현해보도록 하겠습니다.
생성한 main.fxml을 우클릭한 뒤 Open with SceneBuilder를 클릭해 주세요
그러면 위와같이 SceneBuilder이 실행됩니다. 여기서 UI를 구성하면 자동으로 main.fxml의 코드가 수정됩니다. UI 컴포넌트들은 좌측 상단에서 끌어다 쓸 수 있습니다.
Containers 에서 pane를 먼저 끌어나 놓고 그 뒤에 controls에서 button을 끌어다 놓아주시면 됩니다. 그 뒤에 Ctrl + s를 눌러 저장을 해 주시고 SceneBuilder는 꺼 주셔도 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import java.lang.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.layout.AnchorPane?> <AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.MainGUIController"> <children> <Pane prefHeight="200.0" prefWidth="200.0"> <children> <Button fx:id="buttonTest" layoutX="73.0" layoutY="89.0" mnemonicParsing="false" text="Button" /> </children> </Pane> </children> </AnchorPane> | cs |
그러면 main.fxml의 코드가 바뀌어 있을것 입니다. 하지만 UI 작업이 모두 끝난게 아닙니다. button을 컨트롤러에 전달해 주기 위해서 AnchorPane에 fx:controller=""와 Button에 fx:id=""를 추가해 주세요
fx:controller=""에는 컨트롤러가 위치하는 패키지명.컨트롤러 클래스 이름 으로 적어주시면 됩니다.
fx:id=""는 해당 컴포넌트의 id 입니다. java에서 해당 컴포넌트를 사용하기 위한 필드명이라고 생각하시면 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import java.net.URL; import java.util.ResourceBundle; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; public class MainGUIController implements Initializable { @FXML private Button buttonTest; @Override public void initialize(URL arg0, ResourceBundle arg1) { buttonTest.setOnMouseClicked( event -> { System.out.println("test"); }); } } | cs |
다음으로 button의 click 이벤트를 받기 위한 controller 클래스를 선언해 보겠습니다. 우선 controller 클래스를 만들고 Initializable을 implement해 주시고, initialize 메소드를 재정의 해 줍시다.
위 코드를 보시면 9번과 10번라인에 @FXML 어노테이션이 있습니다. FXMLLoader가 FXML 파일을 로딩할 때, 태그로 선언된 컨트롤 객체가 생성되면서 컨트롤러 객체도 함께 생성됩니다. 그 뒤에 @FXML 어노테이션이 적용된 필드에 컨트롤 객체가 자동으로 주입됩니다. 이 때 한가지 조건이 있습니다. 위의 fxml코드에서 fx:id에 설정해 준 아이디와 컨트롤 객체를 주입할 필드의 이름이 같아야 합니다.(buttonTest) 주입이 완료된 뒤에 initialize() 메소드가 호출되기 때문에 initialize() 내부에서 필드를 안전하게 사용할 수 있습니다.
주입이 완료된 button 객체에 initialize메소드에서 MouseClickEvent를 등록해 주시고, 람다식을 통해 익명클래스를 구현해 주세요. 내부의 내용은 용도에 따라 작성해 주셔도 좋지만, 오늘은 테스트니 test 문자열을 출력하도록 하겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class Main extends Application { @Override public void start(Stage primaryStage) { try { Parent root = FXMLLoader.load(getClass().getResource("main.fxml")); Scene scene = new Scene(root,400,400); scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); primaryStage.setTitle("AppMain"); primaryStage.setScene(scene); primaryStage.show(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { launch(args); } } | cs |
마지막으로 Main 클래스의 start 메소드에 가서 코드를 위와 같이 수정해 주시면 됩니다.
■Controller
위의 무작정 따라해보기 만으로는 Controller에 대한 이해가 정확히 되지 않으셨으리라 생각합니다. 프로그램적으로 레이아웃을 구성하고 이벤트까지 처리하게되면 그 코드는 매우 복잡해질것 입니다. (마치 Swing처럼..) 그래서 JavaFX는 FXML 파일당 별도의 Controller를 지정해 이벤트를 처리한다고 위에서도 설해명드렸습니다.
그럼 controller를 정확히 어떻게 사용하는지 알아보도록 하겠습니다.
fx:controller 속성
위의 무작정 따라해보기 파트의 fxml코드에서 보셨을 것 입니다. 바로 fx:controller속성이 fxml에 controller를 지정하는 핵심 코드 입니다.
1 2 3 4 5 | <RootContainer xmlns:fx="http://javafx.com/fxml" fx:controller="packageName.ControllerName"> ... </RootContainer> | cs |
그 뒤에 실제적으로 controller를 구현하는 코드는 아래와 같이 Initializable인터페이스를 구현해 주시면 됩니다.
1 2 3 4 | public class ControllerName implements Initializable { @Override public void initialize(URL location, ResourceBundle resources) { ... } } | cs |
구현된 initialize메소드는 컨트롤러 객체가 생성되고 나서 호출됩니다. 해당 메소드에는 주로 UI 컨트롤의 초기화, 이벤트 핸들러 등록, 속성 감시 등의 코드가 작성됩니다.
이상입니다. 저도 배우면서 쓰는 입장이라 많이 조잡하고 복잡한 감이 있네요.
'프로그래밍 > java' 카테고리의 다른 글
Java - 직렬화(Serialization) (403) | 2016.11.23 |
---|---|
JVM 과 메모리 구조 (0) | 2016.11.23 |
Java - JavaFX 시작하기 (4) | 2016.10.13 |
Java - 엑셀 읽기/쓰기 (Excel Read/Write) (7) | 2016.09.22 |
java - 스레드 동기화(thread synchronization) (0) | 2016.07.23 |