2014-04-23 2 views
0

저는 JavaFX를 처음 접했고 JavaFX에서이 원리를 달성하려고합니다. Student 객체로 채워진 TableView가 있습니다. 첫 번째 열을 선택한 항목에 대해 대량 작업을 수행하기 위해 각 행을 선택할 수있는 확인란으로 지정해야합니다 (일반적으로 메일 응용 프로그램과 같이 표시됨).JavaFX TableView를 사용하여 목록을 채우는 체크 박스

나는보기 레이어에서만 사용되므로 SimpleBooleanProperty를 Student 클래스에 추가하면 안된다. 그래서 나는 이것을 다음과 같이 구현할 수 있다고 생각했다 : 체크 박스를 선택하면 학생이 추가된다. 목록 selectedStudents; 선택을 취소하면 제거됩니다. 이것은 좋은 접근 방법입니까?

private class CheckBoxCell extends TableCell<Student, Boolean> { 

    final CheckBox cellCheckBox = new CheckBox(); 

    CheckBoxCell(final TableView tblView) { 

     cellCheckBox.setOnAction(new EventHandler<ActionEvent>() { 

      @Override 
      public void handle(ActionEvent t) { 
       int selectedIndex = getTableRow().getIndex(); 

       if (!cellCheckBox.isSelected()) { 
        getModel().selectStudent(selectedIndex); // add to selectedStudents 
       } else { 
        getModel().deselectStudent(selectedIndex); // remove from selectedStudents 
       } 
      } 
     }); 
    } 

    //Display button if the row is not empty 
    @Override 
    protected void updateItem(Boolean t, boolean empty) { 
     super.updateItem(t, empty); 
     if (!empty) { 
      setGraphic(cellCheckBox); 
     } 
    } 
} 

이 코드의 주요 문제이다 -

voornaamKolom.setCellValueFactory(new PropertyValueFactory<Student, String>("name")); 
    familienaamKolom.setCellValueFactory(new PropertyValueFactory<Student, String>("fname")); 
    promotorKolom.setCellValueFactory(new PropertyValueFactory<Student, String>("comment")); 

    selectedKolom.setCellValueFactory(
      new Callback<TableColumn.CellDataFeatures<Student, Boolean>, ObservableValue<Boolean>>() { 

       @Override 
       public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<Student, Boolean> p) { 
        return new SimpleBooleanProperty(p.getValue() != null); 
       } 
      }); 

    selectedKolom.setCellFactory(
      new Callback<TableColumn<Student, Boolean>, TableCell<Student, Boolean>>() { 

       @Override 
       public TableCell<Student, Boolean> call(TableColumn<Student, Boolean> p) { 
        return new CheckBoxCell(studentenTabel); 
       } 

      }); 

    studentenTabel.getItems().setAll(getModel().getStudenten()); 

가 :

내가 (주로 유사한 솔루션에서 복사 붙여 넣기 기준)까지있어 코드입니다 확인란은 테이블 행에 바인딩되지 않습니다. 예 : 두 번째 항목을 선택하고 다른 값을 기준으로 정렬하여 행 순서를 변경하면 두 번째 항목은 다른 개체를 나타내는 경우에도 여전히 선택됩니다. 새로운 행이 테이블에 추가되면 그 중 일부는 무작위로 선택됩니다.

나는이 코드가 아마도 더러운 것이라고 알고있다. 나는 JavaFX에 익숙하지 않다. 어떤 도움을 주시면 감사하겠습니다.

미리 감사드립니다.

답변

0

대신 getModel().selectStudent(selectedObject);getModel().deselectStudent(selectedObject);을 구현할 수 있습니다. 여기서는 selectedObject이 색인이 아닌 객체 자체 여야합니다. 모델은 인덱스 대신 오브젝트를 가리켜 야합니다.

만든 모델과 정확히 일치하는 모델을 만들 수 있다는 것을 기억하십시오. 올바른 객체가 가리키고 있는지 확인해야합니다.

+0

좋은 소리지만, selectedIndex의 내가 getTableRow()에 할당 된 변수입니다. getIndex() 라인에서 위 및 방법 getTableRow() 존재없는 것 같다.으로 getObject()을. 대신 무엇을 사용할 수 있습니까? – lukasvo

+0

'getTableRow(). getItem()'을 사용하면 현재 행에서'Student' 객체를 얻을 수 있습니다. 그러나 내 (다소 다른) 솔루션을보십시오. –

+0

James_D가 말했듯이, 그것은'getTableRow(). getItem()'입니다. –

2

확인란의 열의 데이터 형식이 나에게 맞는 것 같습니다. Student; 예 : TableColumn<Student, Student>입니다. 그 이유는 학생이 실제로 전체 대상 자체에 대한 견해를 제시하고 있다는 것입니다 : 선택한 학생 컬렉션에 학생이 포함되어 있습니까? 일종의 반대 직관적이지만 작동하게 만듭니다.

이 예제가 도움이되는지 확인하십시오. 필자는 코드가 암시하는 모델에 데이터를 잘 구분하지 못하지만이를 고려해 볼 수 있어야합니다.

import javafx.application.Application; 
import javafx.beans.property.ReadOnlyObjectWrapper; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.beans.value.ObservableValue; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableSet; 
import javafx.collections.SetChangeListener; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.CheckBox; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.TableColumn.CellDataFeatures; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.stage.Stage; 
import javafx.util.Callback; 

public class SelectableTable extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     TableView<Item> itemTable = new TableView<>(); 
     for (int i=1; i<=40; i++) { 
      itemTable.getItems().add(new Item("Item "+i)); 
     } 
     TableColumn<Item, String> nameCol = new TableColumn<>("Name"); 
     nameCol.setCellValueFactory(new PropertyValueFactory<>("name")); 


     TableColumn<Item, Item> selectedCol = new TableColumn<>("Select"); 

     // Collection of items currently selected via checkboxes in the table 
     // This will be passed to the TableCell implementation. 
     ObservableSet<Item> selectedItems = FXCollections.observableSet(); 

     selectedCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Item,Item>, ObservableValue<Item>>() { 

      @Override 
      public ObservableValue<Item> call(CellDataFeatures<Item, Item> data) { 
       return new ReadOnlyObjectWrapper<>(data.getValue()); 
      } 
     }); 

     selectedCol.setCellFactory(new Callback<TableColumn<Item, Item>, TableCell<Item, Item>>() { 

      @Override 
      public TableCell<Item, Item> call(
        TableColumn<Item, Item> param) { 
       return new CheckBoxCell(selectedItems); 
      } 
     }); 

     itemTable.getColumns().addAll(selectedCol, nameCol); 

     Button displayButton = new Button("Display selected"); 
     displayButton.setOnAction(new EventHandler<ActionEvent>() { 

      @Override 
      public void handle(ActionEvent event) { 
       for (Item item : selectedItems) { 
        System.out.println(item.getName()); 
       } 
      } 
     }); 

     Button selectAllButton = new Button("Select all"); 
     selectAllButton.setOnAction(new EventHandler<ActionEvent>() { 

      @Override 
      public void handle(ActionEvent event) { 
       selectedItems.addAll(itemTable.getItems()); 
      } 
     }); 

     Button selectNoneButton = new Button("Select none"); 
     selectNoneButton.setOnAction(new EventHandler<ActionEvent>() { 

      @Override 
      public void handle(ActionEvent event) { 
       selectedItems.clear(); 
      } 
     }); 

     HBox buttons = new HBox(5); 
     buttons.getChildren().addAll(selectAllButton, selectNoneButton, displayButton); 

     BorderPane root = new BorderPane(); 
     root.setCenter(itemTable); 
     root.setBottom(buttons); 

     Scene scene = new Scene(root, 400, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

    } 

    public static class CheckBoxCell extends TableCell<Item, Item> { 

     private final ObservableSet<Item> selectedItems ; 
     private final CheckBox checkBox ; 

     public CheckBoxCell(ObservableSet<Item> selectedItems) { 
      this.selectedItems = selectedItems ; 
      this.checkBox = new CheckBox() ; 


      // listener to update the set of selected items when the 
      // check box is checked or unchecked: 
      checkBox.setOnAction(new EventHandler<ActionEvent>() { 

       @Override 
       public void handle(ActionEvent event) { 
        if (checkBox.isSelected()) { 
         selectedItems.add(getItem()); 
        } else { 
         selectedItems.remove(getItem()); 
        } 
       } 
      }); 

      // listener to update the check box when the collection of selected 
      // items changes: 
      selectedItems.addListener(new SetChangeListener<Item>() { 

       @Override 
       public void onChanged(Change<? extends Item> change) { 
        Item item = getItem(); 
        if (item != null) { 
         checkBox.setSelected(selectedItems.contains(item)); 
        } 
       } 

      }); 
     } 

     @Override 
     public void updateItem(Item item, boolean empty) { 
      super.updateItem(item, empty); 
      if (empty) { 
       setGraphic(null); 
      } else { 
       checkBox.setSelected(selectedItems.contains(item)); 
       setGraphic(checkBox); 
      } 
     } 
    } 

    public static class Item { 
     private final StringProperty name = new SimpleStringProperty(this, "name"); 
     public StringProperty nameProperty() { 
      return name ; 
     } 
     public final String getName() { 
      return name.get(); 
     } 
     public final void setName(String name) { 
      this.name.set(name); 
     } 
     public Item(String name) { 
      setName(name); 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

영웅! 학생, 학생은 실제로 반 직관적 인 것처럼 보이지만 완벽하게 트릭을합니다. 고마워요! – lukasvo

관련 문제