tutorial - javafx教學




在JavaFX的表格中獲取複選框值 (4)

我有一個表,它有一個複選框的行。

我想要做的是在按鈕點擊我想找出什麼複選框被選中,哪些不是。 到目前為止,我設法在表中創建複選框。 代碼如下。

public class TTEs implements Initializable{

@FXML
private TableView<TestObject> tableReport;

@FXML
private TableColumn<TestObject, String> name;

@FXML
private TableColumn<TestObject, Boolean> checkbox;


@FXML
public void getValues(){        
    //the method will get what check boxes are checked (this part is the problem)
}


@Override
public void initialize(URL arg0, ResourceBundle arg1) {


     ObservableList<TestObject> data = FXCollections.observableArrayList();
     data.add(new TestObject("Test 1", true));
     data.add(new TestObject("Test 2", false));

     tableReport.setItems(data);

     name.setCellValueFactory(new PropertyValueFactory<TestObject, String>("name"));
     checkbox.setCellValueFactory(new PropertyValueFactory<TestObject, Boolean>("checked"));

     checkbox.setCellFactory(new Callback<TableColumn<TestObject, Boolean>, TableCell<TestObject, Boolean>>() {

            public TableCell<TestObject, Boolean> call(TableColumn<TestObject, Boolean> p) {
                return new CheckBoxTableCell<TestObject, Boolean>();
            }
        });

}


//CheckBoxTableCell for creating a CheckBox in a table cell
public static class CheckBoxTableCell<S, T> extends TableCell<S, T> {
    private final CheckBox checkBox;
    private ObservableValue<T> ov;

    public CheckBoxTableCell() {
        this.checkBox = new CheckBox();
        this.checkBox.setAlignment(Pos.CENTER);

        setAlignment(Pos.CENTER);
        setGraphic(checkBox);
    } 

    @Override public void updateItem(T item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            setGraphic(checkBox);
            if (ov instanceof BooleanProperty) {
                checkBox.selectedProperty().unbindBidirectional((BooleanProperty) ov);
            }
            ov = getTableColumn().getCellObservableValue(getIndex());
            if (ov instanceof BooleanProperty) {
                checkBox.selectedProperty().bindBidirectional((BooleanProperty) ov);
            }
        }
    }
}

}

當我調試時,我發現,

        ov = getTableColumn().getCellObservableValue(getIndex());
        if (ov instanceof BooleanProperty) {
            checkBox.selectedProperty().bindBidirectional((BooleanProperty) ov);
        }

在上述的情況下,如果沒有進入。 意思是ovis i = nota實例如果是布爾屬性。 但是當我打印ov的類時,

System.out.println(ov.getClass().getName());

它打印為

javafx.beans.property.ReadOnlyObjectWrapper

ReadOnlyObjectWrapperBooleanProperty的一個子類


一個小題目 - 但在Kotlin你可以這樣做:

    isPvtColumn.cellFactory = Callback { CheckBoxTableCell<KeyWithProperties, Boolean>() }

    isPvtColumn.cellValueFactory = Callback {
        a -> a.value.private
    }

這就是它的全部


你的方法的主要問題是CheckBoxTableCell用法:Cell是一個重複使用的“渲染”機器。 如果你試圖添加一個狀態,比如CheckBox變量,你就麻煩了。

對您的問題最簡單的解決辦法是每次分配複選框。 以下代碼提供了一個工作複選框列:

public static class Member {
    private StringProperty myName;
    private BooleanProperty myCheck;

    public Member(String name, boolean checked) {
        myName = new SimpleStringProperty(name);
        myCheck = new SimpleBooleanProperty(checked);
    }

    public StringProperty nameProperty() { return myName; }    
    public BooleanProperty checkProperty() { return myCheck; }
}

VBox testTable6(VBox box) { // check box bind to cell property
    ObservableList<Member> members = FXCollections.observableArrayList();

    members.add(new Member("peter", true));
    members.add(new Member("gernot", true));
    members.add(new Member("fritz", false));

    TableView<Member> table = new TableView<Member>();
    table.prefHeightProperty().bind(box.heightProperty());
    table.setItems(members);

    TableColumn<Member,String> c1 = new TableColumn<Member,String>("Name");
    c1.setCellValueFactory(new PropertyValueFactory<Member,String>("name"));
    table.getColumns().add(c1);

    TableColumn<Member,Boolean> c2 = new TableColumn<Member,Boolean>("Membercheck");
    c2.setCellValueFactory(new PropertyValueFactory<Member,Boolean>("check"));
    c2.setCellFactory(column -> new TableCell<Member, Boolean>(){
        public void updateItem(Boolean check, boolean empty) {
            super.updateItem(check, empty);
            if (check == null || empty) {
                setGraphic(null);
            } else {
                CheckBox box = new CheckBox();
                BooleanProperty checked = (BooleanProperty)column.getCellObservableValue(getIndex());
                box.setSelected(checked.get());
                box.selectedProperty().bindBidirectional(checked);
                setGraphic(box);
            }
        }
    }
            );
    table.getColumns().add(c2);

    box.getChildren().addAll(table);
    return box;
}

由於雙向屬性綁定是一個弱綁定,所以即使您無法明確解綁,carbage集合也能正常工作。

無論如何,在這裡,未經檢查的轉換為BooleanProperty並不是一個好的樣式,對不起。 考慮使用以下命令訪問整個對象:

...
Member member = table.getItems().get(getIndex());
box.setSelected(member.checkProperty().get());
box.selectedProperty().bindBidirectional(member.checkProperty());
....

順便說一句:雙向綁定不會在那一刻設置選定的屬性,只有當它被改變後! 所以明確的任務:

box.setSelected(member.checkProperty().get());

這裡是強制性的。


在初始化方法中,切換JavaFX提供的自定義工廠:

@Override
public void initialize(URL arg0, ResourceBundle arg1) {

     ObservableList<TestObject> data = FXCollections.observableArrayList();
     data.add(new TestObject("Test 1", true));
     data.add(new TestObject("Test 2", false));

     tableReport.setItems(data);

     name.setCellValueFactory(new PropertyValueFactory<TestObject, String>("name"));
     checkbox.setCellValueFactory(new PropertyValueFactory<TestObject, Boolean>("checked"));

     checkbox.setCellFactory(
         CheckBoxTableCell.forTableColumn(checkbox)
     );

}

現在你的數據綁定到列,你可以遍歷項目,並檢查“檢查”字段:

@FXML
public void getValues(){        
    ObservableList<TestObject> data = tableReport.getItems();

    for (TestObject item : data){
        //check the boolean value of each item to determine checkbox state
    }
}

循環遍歷TableView的數據模型,檢查綁定到每個CheckBox的布爾值。

@FXML
public void getValues(){        
    ObservableList<TestObject> data = tableReport.getItems();

    for (TestObject item : data){
        //check the boolean value of each item to determine checkbox state
    }
}






javafx-2