【问题标题】:Delete a TableViev Row on selecting a checkbox in that row and in the last column在选择该行和最后一列中的复选框时删除 TableViev 行
【发布时间】:2022-01-26 20:16:21
【问题描述】:

我正在尝试这样做,以便每当我在 tableviwew 的最后一列中选择一个复选框时,我都会删除该行。我有一个任务对象,我用相关字段字符串名称、字符串 dateString 和布尔 tickOff 输入到 tableview 中。有人可以帮忙吗?

这是那个班级:

public class Task {

private BooleanProperty tickOff;
private String name;
private String description;
private String dateString;
private String reminder1, reminder2, reminder3, reminder4, reminder5, reminder6;
private int year, month, day;

public Task(String name, String description, int year, int month, int day, boolean ticoff) {
    this.name = name;
    this.description = description;
    this.year = year;
    this.month = month;
    this.day = day;
    dateString = day + "/" + month + "/" + year;
    this.tickOff = new SimpleBooleanProperty(ticoff);
    // this.tickOff = new SimpleBooleanProperty(false);
    /*
     * this.tickOff.addListener(new ChangeListener<Boolean>() { public void
     * changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
     * 
     * System.out.println("Hi");
     * 
     * } });
     */
}

/////////////
public boolean getSelected() {
    return selectedProperty().get();
}

public BooleanProperty selectedProperty() {
    return this.tickOff;
}

public boolean isChecked() {
    return this.tickOff.get();
}

public boolean getickOff() {
    return this.tickOff.get();
}

public BooleanProperty getTickOff() {
    return this.tickOff;
}

public BooleanProperty checkedProperty() {
    return this.tickOff;
}

这是 tableviwew 所在场景的 Controller 类。

public class ClassPlanController {


private TableView<Task> tasks;
@FXML
private TableColumn<Task, String> task;
@FXML
private TableColumn<Task, String> date;
@FXML
private TableColumn<Task, Boolean> done;




public void addTaskToList(Task taskName) {
    
    task.setCellValueFactory(new PropertyValueFactory<>("name"));
    date.setCellValueFactory(new PropertyValueFactory<>("dateString"));
    done.setCellValueFactory(new PropertyValueFactory<>("tickOff"));


/*
    done.setCellFactory(CheckBoxTableCell.forTableColumn(new Callback<Integer, ObservableValue<Boolean>>() {

        public ObservableValue<Boolean> call(Integer param) {
            return tasks.getItems().get(param).checkedProperty();
            
        }

    }));
    
    /*
      done.setCellFactory(new Callback<TableColumn<Task, Boolean>, TableCell<Task, Boolean>>() {

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

    });
     
    done.setCellFactory(CheckBoxTableCell.forTableColumn(new Callback<Integer, ObservableValue<Boolean>>() {

        public ObservableValue<Boolean> call(Integer param) {

            return tasks.get(param).checkedProperty();

        }

    }));
    
    */
        

    tasks.getItems().add(taskName);
    tasks.setEditable(true);
    
}

【问题讨论】:

  • 如果您真的想保留所有任务(即使是那些未显示在表格中的任务),请使用 FilteredList 并按布尔属性进行过滤。如果您想完全摆脱选中的任务,可能按钮比复选框更有意义。
  • 这不是一个代码编写服务.. 做一些研究,应用你所学到的,然后用minimal reproducible example 来证明问题所在
  • @James_D 我试图让它模拟一个待办事项列表,所以它非常重要
  • @kleopatra 我从未要求编写任何代码。我做了研究,找不到解决方案,大概是我在这里问这个问题的原因。我认为这适合上下文的最小可重复示例,如果有任何遗漏,请随时告诉我,我会更新问题。
  • 你误解了我的意思。您是想完全丢弃该项目(即不再引用它),还是仍想将其保留在内存中(例如,您可以显示已完成的任务等)而不是将其显示在表格中? (无论哪种方式,我想,当您选中复选框时,某些东西会完全从 UI 中消失,这是一种非常奇怪的用户体验。)

标签: java javafx


【解决方案1】:

使用FilteredList

public class ClassPlanController {


    private TableView<Task> tasks;
    @FXML
    private TableColumn<Task, String> task;
    @FXML
    private TableColumn<Task, String> date;
    @FXML
    private TableColumn<Task, Boolean> done;
    
    private final ObservableList<Task> taskList = FXCollections.observableArrayList<>(task -> new Observable[] {task.checkedProperty()});
    
    
    public void initialize() {
        task.setCellValueFactory(new PropertyValueFactory<>("name"));
        date.setCellValueFactory(new PropertyValueFactory<>("dateString"));
        done.setCellValueFactory(cellData -> cellData.getValue().checkedProperty());
    
        done.setCellFactory(column -> new CheckBoxTableCell(index -> tasks.getItems().get(index).checkedProperty()));
    
        tasks.setItems(new FilteredList(taskList, task -> ! task.checkedProperty().get()));
    
    }
    
    public void addTaskToList(Task taskName) {
        
        taskList.add(taskName);
        
    }
}

【讨论】:

  • 它有效,你是个传奇人物。感谢您花时间帮助我。非常感谢!
  • 哟,抱歉又打扰了,快速问一下。有没有办法在任何地方添加 Thread.sleep() 行来延迟删除,我希望复选框出现然后将其删除。谢谢
  • 永远不要在 fx 应用程序线程上休眠。我在 cmets 中说过,正是由于这个原因,这将是一个糟糕的用户体验。
  • @Tomislav 这样做的方法可能是自己实现表格单元格,并在复选框上使用侦听器启动转换并在转换完成时更新模型属性。这是一项相当复杂的工作。
  • @kleopatra 使用过滤列表解决的原始问题是仅显示绑定到复选框的属性为假的项目。这是一种可怕的用户体验,因为您选中一个框,它会立即消失。 OP要求延迟。所以我设想实现单元格,以便在选中框和更新模型之间存在延迟。例如,您可能有一个淡入淡出过渡,它在选中该框时开始,并且在淡入淡出完成时更新模型(并且隐藏项目)。这些都是视图职责。
【解决方案2】:

要允许将 ActionEvents 分配给 CheckBoxTableCell,请创建您自己的名为 CheckBoxTableCell 的类,如下所示:

    private ObservableValue<T> ov;
    private TableView<Task> tableView; //The table that will house the checkbox.

    public CheckBoxTableCell() {

        CheckBox checkBox = new CheckBox();
        this.checkBox = checkBox;

        checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                if (newValue) {
                    // getTableView().getSelectionModel().select( getIndex() );
                    System.out.println("Xd");
                } else {
                    // getTableView().getSelectionModel().clearSelection( getIndex() );
                    System.out.println("Nothing");
                }
            }
        });

        setGraphic(checkBox);

    }

    @Override
    public void updateItem(T item, boolean empty) {
        // System.out.println("updateItem");
        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);

            }

        }

    }

    void setTableView(TableView<Task> tableView) {
        this.tableView = tableView;
    }

    void setTableColumn(TableColumn<Task, Boolean> tableColumn) {
        this.tableColumn = tableColumn;
    }
}

【讨论】:

  • 为什么要重新发明轮子? CheckBoxTableCell 有什么问题?
  • 你的重新发明的几个 cmets:a) 一个空单元格未被选中并且没有图形(好!),但你的构造函数用图形实例化它 b) 带参数的构造函数未使用,删除它c)单元格是错误的地方实现数据相关的逻辑 - 比如删除行 - (就像你似乎打算在选择监听器中做的那样),在数据上实现它d)选择监听器看起来很可疑:它与bidi竞争-绑定,无法保证它们的通知顺序,因此可能(并且可能)对单元重用造成问题
  • 你用这些技术术语迷失了我。在以这种方式实现它之后,我所知道的检查一个复选框实际上做了一些事情(在这种情况下,勾选时打印 1,未勾选时打印 0。)有没有办法添加添加代码来删除它所在的表格行? James_D 告诉我的解决方案可以很好地在单击复选框时从表格中删除,但这样我觉得它更可定制。就像我不仅需要删除行一样,我还需要行索引,因此我可以从将对象存储为 JSON 字符串的文本文件中删除行。
  • 我重新做的原因是因为你导入的常规类(javafx.scene.control.cell.CheckBoxTableCell)在勾选时似乎没有做任何事情,James_D 建议我做我的勾选后拥有一个以编辑事件。他提到使用 getIndex() 来获取单元格的位置,但我似乎无法理解如何实现它。我应该创建一个新问题吗?
  • 打勾时似乎没有做任何事情,这是因为它不应该 - 在模型中实现您的应用程序逻辑(相对于视图中)顺便说一句:对我来说它看起来就像您在地窖前建造顶层公寓一样 - 没有冒犯的意思,但这就是您的 cmets 似乎表明的 :) 换句话说:在您的鞋子中,我会尝试彻底了解 fx 基础知识(特别是关于细胞如何工作的在这种情况下)首先
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-17
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
相关资源
最近更新 更多