【问题标题】:Understanding CheckBoxTableCell changelistener using setSelectedStateCallback使用 setSelectedStateCallback 了解 CheckBoxTableCell 更改侦听器
【发布时间】:2016-01-03 19:46:48
【问题描述】:

我正在尝试关注: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;
        }
    }


}

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

【问题讨论】:

  • 重点是您不要在复选框中添加侦听器,而是向映射到的属性添加侦听器。 IE。只需将侦听器添加到项目的clientHasRequestedFaxProperty()。您可以创建一个minimal reproducible example 并编辑您的问题以包含它吗? (我真的不明白你在用ctCell 做什么以及它与你的表格列的关系。)
  • 是的,让我添加一张我想要实现的图像。之后,我将开始提取最小的工作代码。
  • 让我知道图片和描述是否有意义。我将开始提取代码并尝试做一个最低限度的工作。
  • 没有帮助。 (我真的不明白您认为这张图片将如何解释为什么向 clientHasRequestedFaxProperty() 添加侦听器不起作用。)您需要一个 minimal reproducible example
  • 知道了。给我一秒钟的时间。

标签: javafx


【解决方案1】:

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

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

在您的代码示例中,我不明白 ctCell 的用途。您只需创建它,在其上设置selectedStateCallBack,然后不要对其进行任何操作。和你的表无关,也和你设置的cell factory无关。

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

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;
        }
    }


}

【讨论】:

  • 这种方法更简洁。通过遵循前一种方法,我必须使它复杂化很多。感谢您的耐心等待。
猜你喜欢
  • 2014-10-02
  • 1970-01-01
  • 1970-01-01
  • 2019-03-08
  • 1970-01-01
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
相关资源
最近更新 更多