JavaFX | ListView와 SelectionModel | SelectionModel에 ChangeListener을 설정

이 SelectionModel는 속성의 변경에 대응한 이벤트 처리 기능을 가지고 있다. 예를 들어, SelectionModel에는 SelectedItem라는 속성이 있고, 선택한 항목 등은 getSelectedItem 메소드로 꺼낼 수 있었다.

이 SelectedItem 속성에 “ChangeListener"라는 이벤트 리스너를 설정하여, 값이 변경되었을 때의 이벤트를 파악하고 처리하는 것이 가능하다. ChangeListener는 그 이름과 같이 값이 변경 될 때 발생하는 이벤트(ChangeEvent)를 처리하는 이벤트 리스너이다.

이것은 SelectionModel의 “selectedItemProperty"라는 메소드로 얻은 ReadOnlyObjectProperty라는 클래스의"addListener"메소드로 설정할 수 있다. 설정 방법의 형태는 다음과 같다.

selectionModel.selectedItemProperty().addListener(new ChangeListener() {

    @Override
    public void changed(ObservableValue observable, Object oldVal, Object newVal) {
        // 수행할 처리
    }
});

ChangeListener는 “changed"라는 메소드가 하나 포함되어 있다. 이 메소드는 ObservableValue라는 클래스의 인스턴스와 변경 전, 변경 후의 값을 인수로 전달된다.

“메소드가 하나뿐"이라는 것에 대해 기억하는 사람이 있을 것이다. 이렇게, Java8는 메소드가 하나인 인터페이스는 람다 식으로 대체 할 수 있다. addListener에 의한 이벤트 리스너 설정을 람다 식으로 하면 이렇게 된다.

selectionModel.selectedItemProperty().addListener (
    (ObservableValue observable, Object oldVal, Object newVal) -> {
        // 수행할 처리
    }
);

이쪽이 더 알아보기 쉽다. 이렇게 ChangeListener를 설정하여, 값이 변경되었을 때 (SelectedItem의 값이 바뀌었을 때 = 선택 상태가 변경되었을 때)의 처리를 할 수 있다.

아래와 같이 간단한 사용 예제를 만들어 보자.

package com.devkuma.javafx;
 
import java.net.URL;
import java.util.ResourceBundle;
 
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
 
 
public class AppController implements Initializable {
    @FXML Label label1;
    @FXML ListView list1;
    @FXML Button btn1;
     
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        list1.setItems(FXCollections.observableArrayList());
        list1.getItems().add("One");
        list1.getItems().add("Two");
        list1.getItems().add("Three");
         
        list1.getSelectionModel().selectedItemProperty().addListener(
            (ObservableValue observable, Object oldVal, Object newVal) -> {
                label1.setText(oldVal + " -> " + newVal);
            }
        );
         
        btn1.setOnAction((AtionEvent)->{
            Object obj = list1.getSelectionModel().getSelectedItem();
            label1.setText("you selected: \"" + obj.toString() + "\".");
        });
    }
 
}

목록의 항목을 선택하면 “이전 값 -> 새로운 값"라는 형식으로 값의 변화가 label1에 표시된다. MouseClick를 사용하는 것보다 이쪽이 스마트하지 않은가? MouseClick는 키 조작 등으로 선택 항목을 변경 한 경우에는 이벤트가 발생하지 않지만, ChangeListener를 이용하면 어떤 형태로든 선택 상태가 바뀌면 바로 이벤트가 발생하고 그에 따른 처리 수행을 할 수가 있다.