테이블뷰는 표를 표현한다.
엑셀파일이나 DB에서 가져온 데이터를 추출해서 보여주고 조작하는데 사용할 수 있다.
JavaFX 에서는 테이블을 보여주는 기능 뿐 아니라 데이터를 편집하고 추가하는 것 기능까지 제공한다.
이 포스팅에서는 테이블을 가져와서 Scene 에서 보여주는 것 까지 다룬다.
TableView를 사용하여 디자인도 준수하고 많은 기능이 들어있는 테이블을 사용할 수 있다.
자바는 모든 것을 객체 취급하기 때문에 개념정리가 필요하다.
위의 테이블을 보면 제품의 리스트이다. 데이터베이스를 접속해서 제품과 재고에 대한 정보를 가져온 것 처럼 가상의 데이터를 만들었다. 실제 데이터베이스를 만들어서 가져오는 것은 JavaFX에서 커버할 범위가 아니다. JSP 혹은 스프링 같은 프레임워크나 DB 프로그래밍을 참고한다.
그럼 데이터베이스에서 DB 레코드를 추출해왔다고 하자. 그 다음에 자바에서 할일은 무엇인가? 그 DB는 그냥 행과 열이 있는 연속하는 데이터의 집합일 뿐이다. 자바에서는 클래스를 만들어서 그 데이터를 객체로 구조화해야 한다.
이때 만드는 클래스를 Product 제품 클래스라고 하자.
아래의 소스 코드는 제품의 속성인 이름, 가격, 수량을 가진 클래스를 정의한다.
길어보이지만 IDE의 기능을 활용하면 작성하는 시간이 줄어든다.
자바의 IDE인 인텔리제이나 이클립스에는 생성자 constructor 와 getter 와 setter 를 자동 생성하는 기능이 있다. 변수 이름만 지정하면 바로 만들어 준다. (인텔리제이에서는 [알트] -> [인서트] 메뉴에 있다)
긴 코드를 보면 타이핑할 의욕이 떨어지기 때문에 꼭 활용해야 하는 기능이다.
package com;
public class Product {
private String name;
private long price;
private int quantity;
public Product() {
this.name = "";
this.price = 0;
this.quantity = 0;
}
public Product(String name, long price, int quantity) {
this.name = name;
this.price = price;
this.quantity = quantity;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getPrice() {
return price;
}
public void setPrice(long price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
getter 와 setter는 객체지향 프로그래밍의 특징인데 private 인 내부 속성에 외부에서 접근하기 위해서 만든다.
* 클래스를 만들었다면 다음은 메인 코드를 작성한다.
자바 코드는 항상 좀 길어보인다. 코드가 길어지는 것은 객체지향의 규칙을 엄격하게 지키기 위해서이다. 하나하나 읽으면서 시간을 보내기 보다 구역별로 분리하며 읽으면 코드를 파악하는게 도움이 된다.
package com;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
Stage window;
Scene scene;
Button button;
TableView<Product> tableView;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
window.setTitle("Learning JavaFX");
button = new Button("전송하기");
// Name
TableColumn<Product, String> nameColumn = new TableColumn<>("NAME");
nameColumn.setMinWidth(150);
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
// Price
TableColumn<Product, Long> priceColumn = new TableColumn<>("PRICE");
priceColumn.setMinWidth(150);
priceColumn.setCellValueFactory(new PropertyValueFactory<>("price"));
// Price
TableColumn<Product, Integer> quantityColumn = new TableColumn<>("QT");
quantityColumn.setMinWidth(100);
quantityColumn.setCellValueFactory(new PropertyValueFactory<>("quantity"));
tableView = new TableView<>();
tableView.setItems(getProduct());
tableView.getColumns().addAll(nameColumn, priceColumn, quantityColumn);
VBox layout = new VBox(20);
layout.setPadding(new Insets(10,10,10,10));
layout.getChildren().add(tableView);
layout.getChildren().add(button);
scene = new Scene(layout, 400, 300);
window.setScene(scene);
window.show();
}
// 모든 product
public ObservableList<Product> getProduct(){
ObservableList<Product> products = FXCollections.observableArrayList();
products.add(new Product("노트북", 1200000L, 20));
products.add(new Product("아이패드", 900000L, 70));
products.add(new Product("카메라", 400000L, 45));
products.add(new Product("모니터", 450000L, 30));
products.add(new Product("스마트TV", 350000L, 40));
return products;
}
}
코드를 보면 TableView<> 제너릭 타입이다. 위에서 만든 Product를 대입한다.
TableColumn 과 PropertyValueFactory도 javafx 의 제너릭이다. 이런 방식으 테이블 칼럼 제네릭을 생성한다.
여기 나오는 width 는 한개의 쎌에 있는 열의 길이이고, NAME (표시되는 문자열) name (Product 클래스의 속성) 이다.
tableView를 생성하여 Product 의 인스턴스를 가져오는 것과 위에서 TableColumn 으로 설정한 테이블을 더한다 addAll
레이아웃에는 tableView를 추가한다.
밑의 getProduct는 ObservableList 를 사용한다. 리스트의 일종으로 JavaFx의 콤포넌트를 취급하는 클래스이다.
그렇다. 모르는 클래스들이 많이 등장한다. 모든 클래스에 대해서 알고 있을 필요는 없다. 그보다는 어디 왜에 쓰이는지, 언제 사용해야 하는지, 프로그램을 유지보수하기 위한 변경 시에는 다른 대안이 있는지? 를 찾는 것이 좋다.
그리고 자주 사용하는 기능들은 본인 스스로가 클래스로 만들어 사용하는게 좋다. 하나의 엔진이나 모듈처럼 코드를 미리 짜놓는다면 복잡할 일이 줄어든다. 타인이 만든 라이브러리, 클래스를 어떻게 하면 나에게 맞게 잘 사용할 수 있을지는 프로그래머의 해결해야할 중요한 문제다.