我正在尝试根据是否勾选了TextFieldTableCell
(位于同一行)来设置CheckBoxTableCell
的可编辑性。因此,例如,如果第二行的复选框被打勾,如下所示,则“ B”处的文本应可编辑。如果未选中该复选框,则“ B”应不可编辑。
我的计划是在TextFieldTableCell
的{{1}}的“选定”侦听器中设置CheckBoxTableCell
的可编辑性。另外,我可以在setCellFactory
的{{1}}中进行设置。
但是,无论哪种方式,我首先必须获取与单击的TableView
位于同一行的ListChangeListener
对象。
我该怎么做?我被困了几天试图找出答案。
这是TextFieldTableCell
的“选定”侦听器的代码段,其中显示了我要执行的操作和遇到的问题:
CheckBoxTableCell
我已经阅读并尝试了Make individual cell editable in JavaFX tableview,Javafx, get the object referenced by a TableCell和Tableview make specific cell or row editable。虽然我认为我了解它们,但我无法使其适应我想要做的事情。
这是上面显示的示例的MVCE。
我正在使用JavaFX8(JDK1.8.0_181),NetBeans 8.2和Scene Builder 8.3。
CheckBoxTableCell
答案 0 :(得分:1)
应用用户kleopatra的建议后,我可以使它正常工作。
最简单的解决方案是,如果未勾选CheckBoxTableCell
,则忽略编辑。 TreeTableView : setting a row not editable对此进行了说明,这也是我在下面的MVCE中使用的方法。
或者,可以通过将TextFieldTableCell
绑定到editableProperty()
的值来设置CheckBoxTableCell
的可编辑性。在此处JavaFX weird (Key)EventBehavior接受答案之后,代码如下所示:
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
doUpdate(item, getIndex(), empty);
}
@Override
public void updateIndex(int index) {
super.updateIndex(index);
doUpdate(getItem(), index, isEmpty());
}
private void doUpdate(String item, int index, boolean empty) {
if ( empty || index == getTableView().getItems().size() ) {
setText(null);
} else {
BooleanProperty checkboxProperty = getTableView().getItems().get(getIndex()).checkboxProperty();
editableProperty().bind(checkboxProperty);
}
}
虽然解决方案不是基于获取TextFieldTableCell
的对象(这是我认为我需要做的),但它确实可以满足我的需要(设置一个基于复选框值的文本字段的可编辑性)。谢谢kleopatra向我指出正确的方向。
这是演示解决方案的MVCE。
package test24;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.Observable;
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.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.converter.DefaultStringConverter;
public class Test24 extends Application {
private Parent createContent() {
//********************************************************************************************
//Declare the TableView and its underlying ObservableList and change listener
TableView<TestModel> table = new TableView<>();
ObservableList<TestModel> olTestModel = FXCollections.observableArrayList(testmodel -> new Observable[] {
testmodel.checkboxProperty()
});
olTestModel.addListener((ListChangeListener.Change<? extends TestModel > c) -> {
while (c.next()) {
if (c.wasUpdated()) {
//...
}
}
});
olTestModel.add(new TestModel(false, "A"));
olTestModel.add(new TestModel(false, "B"));
olTestModel.add(new TestModel(false, "C"));
table.setItems(olTestModel);
//********************************************************************************************
//Declare the CheckBox column
TableColumn<TestModel, Boolean> colCheckbox = new TableColumn<>("checkbox");
colCheckbox.setCellValueFactory(cellData -> cellData.getValue().checkboxProperty());
colCheckbox.setCellFactory(CheckBoxTableCell.forTableColumn(colCheckbox));
//********************************************************************************************
//Declare the text column whose editability needs to change depending on whether or
//not the CheckBox is ticked
TableColumn<TestModel, String> colText = new TableColumn<>("text");
colText.setCellValueFactory(cellData -> cellData.getValue().textProperty());
//Don't setEditable() to false here, otherwise updateItem(), updateIndex() and startEdit() won't fire
colText.setEditable(true);
colText.setCellFactory(cb -> {
DefaultStringConverter converter = new DefaultStringConverter();
TableCell<TestModel, String> cell = new TextFieldTableCell<TestModel, String>(converter) {
@Override
public void startEdit() {
boolean checkbox = getTableView().getItems().get(getIndex()).getCheckbox();
if ( checkbox == true ) {
super.startEdit();
}
}
};
return cell;
});
//********************************************************************************************
//Column to show what's actually in the TableView's data model for the checkbox
TableColumn<TestModel, Boolean> colDMVal = new TableColumn<>("data model value");
colDMVal.setCellValueFactory(cb -> cb.getValue().checkboxProperty());
colDMVal.setEditable(false);
table.getSelectionModel().setCellSelectionEnabled(true);
table.setEditable(true);
table.getColumns().add(colCheckbox);
table.getColumns().add(colDMVal);
table.getColumns().add(colText);
BorderPane content = new BorderPane(table);
return content;
}
public class TestModel {
private BooleanProperty checkbox;
private StringProperty text;
public TestModel() {
this(false, "");
}
public TestModel(
boolean checkbox,
String text
) {
this.checkbox = new SimpleBooleanProperty(checkbox);
this.text = new SimpleStringProperty(text);
}
public Boolean getCheckbox() {
return checkbox.get();
}
public void setCheckbox(boolean checkbox) {
this.checkbox.set(checkbox);
}
public BooleanProperty checkboxProperty() {
return checkbox;
}
public String getText() {
return text.get();
}
public void setText(String text) {
this.text.set(text);
}
public StringProperty textProperty() {
return text;
}
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.setTitle("Test");
stage.setWidth(500);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}