Programing/JavaFX

JavaFx scene builder TableView 표출 및 갱신 방법

리커니 2021. 3. 26.
반응형

JavaFx scene builder TableView 표출 및 갱신 방법

 

이번 포스팅에서는 JavaFx 의 TableView를 다루는 방법을 알아보겠습니다.

TableView 는 우리가 일반적으로 알고 있는 그리드(리스트) 입니다. 

 

우선 Scene builder를 열어 창의 구조를 잡고 ScrollPane 안에 TableView를 추가해 줍니다.

그리고 TableColumn을 추가하여 테이블의 헤더를 설정해 줍니다.

그럼 아래와 같은 구조가 되게 됩니다.

 

이제 우측 Code Tab에서 fx:id를 설정해 줍니다.

 

각각의 열에도 같은 방식으로 fx:id 를 설정해 줍니다. (컬럼명)

 

 

이제 Scene builder 메뉴바에서 View > Show simple controller skeleton 을 선택해

연결된 클래스의 샘플 코드를 복사 합니다. (연결된 Controller는 좌측 Controller 탭에 있습니다.)

복사한 내용을 연결된 패키지 내 컨트롤러에 붙여넣기 합니다. 

 

[MainConrtroller.class] Scene builder 에서 연결한 controller

@FXML
private TableView<EquipTblVO> equipTbl;
    
@FXML
private TableColumn<EquipTblVO, String> mstLcsId;
    
@FXML
private TableColumn<EquipTblVO, String> mstLcsIp;

@FXML
private TableColumn<EquipTblVO, String> connLcsId;
    
@FXML
private TableColumn<EquipTblVO, String> connLcsIp;
    
@FXML
private TableColumn<EquipTblVO, String> connLcsStat;
    
@FXML
private TableColumn<EquipTblVO, String> equipStat;

 

그리고 @Override 된 initiallize 메소드 내에 전역에 설정해 둔 static변수에 담습니다. 

(저의 경우에는 다른 패키지의 메소드에서 접근하는 경우가 있어 static class에 변수를 선언해 놨습니다.)

 

[CmmnVar.class] static class


public class CmmnVar {
    .
    .
    .
	public static TableView<EquipTblVO> equipTbl = new TableView<EquipTblVO>();
	public static TableColumn<EquipTblVO, String> mstLcsIp = new TableColumn<EquipTblVO, String>();
	public static TableColumn<EquipTblVO, String> connLcsIp = new TableColumn<EquipTblVO, String>();
	public static TableColumn<EquipTblVO, String> connLcsId = new TableColumn<EquipTblVO, String>();
	public static TableColumn<EquipTblVO, String> mstLcsId = new TableColumn<EquipTblVO, String>();
	public static TableColumn<EquipTblVO, String> connLcsStat = new TableColumn<EquipTblVO, String>();
	public static TableColumn<EquipTblVO, String> equipStat = new TableColumn<EquipTblVO, String>();
    .
    .
    .
}

 

 

[MainConrtroller.class] Scene builder 에서 연결한 controller

 

@Override
public void initialize(URL location, ResourceBundle resources) {
    CmmnVar.equipTbl = equipTbl;
    /*테이블에 데이터가 없을 경우 표출 문구*/
    CmmnVar.equipTbl.setPlaceholder(new Label("데이터가 존재하지 않습니다."));
	CmmnVar.mstLcsId.setCellValueFactory(new PropertyValueFactory<EquipTblVO, String>("mstLcsId"));
    CmmnVar.mstLcsIp.setCellValueFactory(new PropertyValueFactory<EquipTblVO, String>("mstLcsIp"));
    CmmnVar.connLcsId.setCellValueFactory(new PropertyValueFactory<EquipTblVO, String>("connLcsId"));
    CmmnVar.connLcsIp.setCellValueFactory(new PropertyValueFactory<EquipTblVO, String>("connLcsIp"));
    CmmnVar.connLcsStat.setCellValueFactory(new PropertyValueFactory<EquipTblVO, String>("connLcsStat"));
    CmmnVar.connLcsStat.setCellFactory(new Callback<TableColumn<EquipTblVO,String>, TableCell<EquipTblVO,String>>() {
        @Override
        public TableCell<EquipTblVO, String> call(TableColumn<EquipTblVO, String> param) {
            return new TableCell<EquipTblVO, String>(){
                @Override
                public void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
                    if(empty || item == null) {
                        setText("");
                        setGraphic(null);
                    }else {
                        if(item.equals("연결")) {
                            setTextFill(Paint.valueOf("#01DF01"));
                        }else {
                            setTextFill(Paint.valueOf("#FF0000"));
                        }
                        setText(item);
                    }
					}
				};
			}
		});
		CmmnVar.equipStat.setCellValueFactory(new PropertyValueFactory<EquipTblVO, String>("equipStat"));
		CmmnVar.equipStat.setCellFactory(new Callback<TableColumn<EquipTblVO,String>, TableCell<EquipTblVO,String>>() {
			@Override
			public TableCell<EquipTblVO, String> call(TableColumn<EquipTblVO, String> param) {
				TableCell<EquipTblVO, String> cell = new TableCell<EquipTblVO, String>(){
					@Override
					public void updateItem(String item, boolean empty) {
						super.updateItem(item, empty);
						if(empty || item == null) {
							setText("");
							setGraphic(null);
						}else {
							
							if(item.indexOf("1") == -1) {
								setTextFill(Paint.valueOf("#01DF01"));
								setText("정상");
							}else {
								if(item.indexOf("1") != 8) {
									setTextFill(Paint.valueOf("#FF0000"));
									setText("이상");
									if(!"".equals(item)) {
										setOnMouseClicked(event -> {
											Parent root = null;
											try {
												root = FXMLLoader.load(getClass().getResource("/view/EquipStatus.fxml"));
												EquipStatPopController c = new EquipStatPopController();
												int rowIdx = getTableRow().getIndex();
												c.initData(CmmnVar.equipList.get(rowIdx).getEquipStat());
												Stage stage = new Stage();
												stage.setTitle(CmmnVar.equipList.get(rowIdx).getConnLcsId()+" 상세 상태 정보");
												stage.getIcons().add(new Image(getClass().getResourceAsStream("/icon/icon.png")));
												stage.initModality(Modality.APPLICATION_MODAL);
												stage.setResizable(false);
												stage.setScene(new Scene(root));
												stage.show();
											} catch (IOException ioe) {
												LOGGER.error("팝업 뷰 파일 로드 에러", ioe);
											} catch (Exception e) {
												try {
													CmmnVar.queue.put("장비 상태정보 팝업을 여는데 실패하였습니다.");
												} catch (InterruptedException e1) {
													LOGGER.error("Pring Log Error", e1);
												}
												LOGGER.error("장비 상태정보 팝업 오픈 에러", e);
											}
										});
									}
								}else {
									setTextFill(Paint.valueOf("#01DF01"));
									setText("정상");
								}
							}
						}
					}
				};
				return cell;
			}
		});

    .
    .
    .
}

 

이 부분이 데이터를 가져왔을 때 데이터-컬럼 간 매핑 설정을 하는 부분입니다. 

단순 매핑의 경우 아래와 같이 설정해주시면 됩니다.

 

CmmnVar.mstLcsId.setCellValueFactory(new PropertyValueFactory<EquipTblVO, String>("mstLcsId"));

 

허나, 가져온 데이터의 값에 따라 내용을 변경하거나 이벤트를 추가해줘야 할 경우에는 setCellFactory 메소드를 사용해 주어야 합니다. 

 

예를들어 위의 connLcsStat 컬럼의 경우 '연결' 이라는 데이터가 있을 경우 글짜의 색을 녹색으로, 없을 경우 붉은 색으로 바꾸기 위해 updateItem 함수를 Override 하여 작성하였습니다. 

중요한 부분은 Override 된 updateItem 메소드의 if문인데요, if(empty || item == null) 이 조건을 주지 않을 경우 원하는 데로 표출이 되지 않습니다. 항상 null이 아닐 경우에만 표출되도록 조건을 추가해주세요.

 

그리고 테이블 컬럼의 click 이벤트를 추가할 경우에는 위와 같이 setOnMouseClicked 메소드를 사용합니다. 

위의 코드 같은 경우 클릭을 하면 장비 상태 팝업을 표출하는 코드입니다. 

TableView의 TableColumn에 Event 를 주고 싶을 경우 위의 equipStat 세팅 코드를 참고하시면 됩니다. 

 

이제 데이터를 테이블에 표출 하는 방법을 알아보겠습니다. 

ObservableList에 가져온 데이터를 추가하여 ObservableList를 Tableview의 item 에 set 해주시면 됩니다. 

주의 할 점은 JavaFx에서 UI를 변경 할 경우에는 JavaFX Thread를 사용하여야 합니다. 

 

[CmmnVar.class] setTblRows method

public static void setTblRows() throws Exception{
    try {
        if (equipTbl != null && equipTbl.getItems() != null) {
            Platform.runLater(new Runnable() {
                 @Override
                 public void run() {
                     ObservableList<EquipTblVO> list = FXCollections.observableArrayList();
                     if(equipList != null) {
                         list.addAll(equipList);
                     }
                     equipTbl.getItems().clear();
                     equipTbl.setItems(list);
                 }
            });
         }	
    }catch(NullPointerException e1) {
        CmmnVar.queue.put("UI 테이블 세팅에 실패하였습니다.");
        LOGGER.error("테이블 세팅 에러 null point exception ", e1);
        CmmnVar.equipList = CmmnVar.service.getLcsMst();
    }catch(IndexOutOfBoundsException e2) {
        LOGGER.error("테이블 세팅 에러 out of bounds exception ", e2);
    }catch(Exception e) {
        LOGGER.error("테이블 세팅 에러 exception ", e);
    }
}

데이터에 변경이 있을 경우 위와 같이 데이터를 갱신하시면 됩니다. 

getItems().clear(); 는 테이블 행열 초기화.

setItems(); 는 데이터 삽입입니다.

 

- JavaFX TableView 데이터 갱신

- javaFX TableView Column formatter

- javaFX TableView Column Click Event

반응형

댓글

💲 추천 글