使用setSelectedStateCallback了解CheckBoxTableCell changelistener

时间:2015-10-06 19:02:50

标签: javafx

我正在尝试关注:CheckBoxTableCell changelistener not working

该问题的给定代码答案如下,取决于模型“培训生”

final CheckBoxTableCell<Trainee, Boolean> ctCell = new CheckBoxTableCell<>();
ctCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
    @Override
    public ObservableValue<Boolean> call(Integer index) {
        return table.getItems().get(index).selectedProperty();
    }
});

我想获取所选的属性值并为其添加一个监听器,但我不认为我做得对。我试图添加所有类型的侦听器,以便我知道每行中的复选框何时更改,我可以为每个添加逻辑。我假设上面的代码允许ctCell现在观察更改,我可以调用一个更改侦听器并检测每个给定行的选择。

我在这里尝试了一些更改属性来检测更改:

ctCell.selectedStateCallbackProperty().addListener(change -> {
    System.out.println("1Change happened in selected state property");
});
ctCell.selectedProperty().addListener(change -> {
    System.out.println("2Change happened in selected property");
});
ctCell.itemProperty().addListener(change -> {
    System.out.println("3Change happened in item property");
});
ctCell.indexProperty().addListener(change -> {
    System.out.println("4Change happened in index property");
});

......但似乎没有人被召唤。

这是我的缩短设置:

requestedFaxCol.setCellValueFactory(new PropertyValueFactory("clientHasRequestedFax"));
requestedFaxCol.setCellFactory(CheckBoxTableCell.forTableColumn(requestedFaxCol));

final CheckBoxTableCell<ClinicClientInfo, Boolean> ctCell = new CheckBoxTableCell<>();

ctCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
       @Override
       public ObservableValue<Boolean> call(Integer index) {
           return clinicLinkTable.getItems().get(index).clientHasRequestedFaxProperty();}
});

如果我需要提供更多信息,请告诉我们!对于为什么我无法将更改侦听器桥接到表格单元格复选框,我不理解什么?或者,如果有人可以指出我尝试的方向。谢谢!

更新以描述此问题的最终目标

package testapp;

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;


public class TestApp extends Application {

    private TableView<ClinicClientInfo> clientTable = new TableView<>();
    private TableColumn<ClinicClientInfo, String> faxCol = new TableColumn<>("Fax");
    private TableColumn<ClinicClientInfo, Boolean> requestedFaxCol = new TableColumn<>("Requested Fax");

    @Override
    public void start(Stage primaryStage) {

        StackPane root = new StackPane();

        ObservableList<ClinicClientInfo> list = FXCollections.observableArrayList(
                new ClinicClientInfo("", false), 
                new ClinicClientInfo("945-342-4324", true));


        root.getChildren().add(clientTable);
        clientTable.getColumns().addAll(faxCol, requestedFaxCol);
        clientTable.setItems(list);
        clientTable.setEditable(true);
        clientTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

        faxCol.setCellValueFactory(new PropertyValueFactory<>("clinicFax"));
        faxCol.setVisible(true);

        requestedFaxCol.setCellValueFactory(new PropertyValueFactory("clientHasRequestedFax"));
        requestedFaxCol.setCellFactory(CheckBoxTableCell.forTableColumn(requestedFaxCol));
        requestedFaxCol.setVisible(true);
        requestedFaxCol.setEditable(true);

        //My attempt to connect the listener
        //If user selects checkbox and the fax value is empty, the alert should prompt
        CheckBoxTableCell<ClinicClientInfo, Boolean> ctCell = new CheckBoxTableCell<>();
        ctCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
            @Override
            public ObservableValue<Boolean> call(Integer index) {

                ObservableValue<Boolean> itemBoolean = clientTable.getItems().get(index).clientHasRequestedFaxProperty();
                itemBoolean.addListener(change -> {

                    ClinicClientInfo item = clientTable.getItems().get(index);

                    if(item.getClinicFax().isEmpty() && item.getClientHasRequestedFax()){
                        Alert alert = new Alert(Alert.AlertType.WARNING);
                        alert.setTitle("Warning");
                        alert.show();
                    }
                });

                return itemBoolean;
            }
        });

        Scene scene = new Scene(root, 300, 250);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    public class ClinicClientInfo {
        private final StringProperty clinicFax;
        private final BooleanProperty clientHasRequestedFax;

        public ClinicClientInfo(String fax, boolean clientHasRequestedFax){
            this.clinicFax = new SimpleStringProperty(fax);
            this.clientHasRequestedFax = new SimpleBooleanProperty(clientHasRequestedFax);
        }

        public String getClinicFax(){
            return clinicFax.get();
        }

        public void setClinicFax(String clinicFax){
            this.clinicFax.set(clinicFax);
        }

        public StringProperty clinicFaxProperty(){
            return clinicFax;
        }

        public boolean getClientHasRequestedFax(){
            return clientHasRequestedFax.get();
        }

        public void setClientHasRequestedFax(boolean clientHasRequestedFax){
            this.clientHasRequestedFax.set(clientHasRequestedFax);
        }

        public BooleanProperty clientHasRequestedFaxProperty(){
            return clientHasRequestedFax;
        }
    }


}

目标是当用户在传真字符串为空时尝试选择传真请求时收到提示。

1 个答案:

答案 0 :(得分:1)

这已经在你已经链接过的问题中得到了充分的解释,所以我不知道除了重述之外我还能添加什么。

单元格中的复选框双向绑定到selectedStateCallback返回的属性。如果未设置selectedStateCallback,并且该单元格已附加到cellValueFactory返回BooleanProperty的列(几乎涵盖所有用例),则复选框的状态为双向绑定到该属性。

在您的代码示例中,我不了解ctCell的用途。您只需创建它,在其上设置selectedStateCallBack,然后不要对其执行任何操作。它与您的桌子无关,与您设置的细胞工厂无关。

因此,在您的情况下,您的单元工厂生成的单元格上没有设置选定的状态回调,并且单元格值工厂返回布尔属性,因此默认值适用,并且复选框状态双向绑定到返回的属性由细胞价值工厂。您所要做的就是为这些属性注册一个监听器。

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;


public class CheckBoxTableCellTestApp extends Application {

    private TableView<ClinicClientInfo> clientTable = new TableView<>();
    private TableColumn<ClinicClientInfo, String> faxCol = new TableColumn<>("Fax");
    private TableColumn<ClinicClientInfo, Boolean> requestedFaxCol = new TableColumn<>("Requested Fax");

    @Override
    public void start(Stage primaryStage) {

        StackPane root = new StackPane();

        ObservableList<ClinicClientInfo> list = FXCollections.observableArrayList(
                new ClinicClientInfo("", false), 
                new ClinicClientInfo("945-342-4324", true));


        // add listeners to boolean properties:
        for (ClinicClientInfo clinic : list) {
            clinic.clientHasRequestedFaxProperty().addListener((obs, faxWasRequested, faxIsNowRequested) ->{
                System.out.printf("%s changed fax request from %s to %s %n", 
                        clinic.getClinicFax(), faxWasRequested, faxIsNowRequested);
            });
        }

        root.getChildren().add(clientTable);
        clientTable.getColumns().addAll(faxCol, requestedFaxCol);
        clientTable.setItems(list);
        clientTable.setEditable(true);
        clientTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

        faxCol.setCellValueFactory(new PropertyValueFactory<>("clinicFax"));
        faxCol.setVisible(true);

        requestedFaxCol.setCellValueFactory(new PropertyValueFactory<>("clientHasRequestedFax"));
        requestedFaxCol.setCellFactory(CheckBoxTableCell.forTableColumn(requestedFaxCol));
        requestedFaxCol.setVisible(true);
        requestedFaxCol.setEditable(true);


        Scene scene = new Scene(root, 300, 250);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    public class ClinicClientInfo {
        private final StringProperty clinicFax;
        private final BooleanProperty clientHasRequestedFax;

        public ClinicClientInfo(String fax, boolean clientHasRequestedFax){
            this.clinicFax = new SimpleStringProperty(fax);
            this.clientHasRequestedFax = new SimpleBooleanProperty(clientHasRequestedFax);
        }

        public String getClinicFax(){
            return clinicFax.get();
        }

        public void setClinicFax(String clinicFax){
            this.clinicFax.set(clinicFax);
        }

        public StringProperty clinicFaxProperty(){
            return clinicFax;
        }

        public boolean getClientHasRequestedFax(){
            return clientHasRequestedFax.get();
        }

        public void setClientHasRequestedFax(boolean clientHasRequestedFax){
            this.clientHasRequestedFax.set(clientHasRequestedFax);
        }

        public BooleanProperty clientHasRequestedFaxProperty(){
            return clientHasRequestedFax;
        }
    }


}