Checkbox TableCell中的复选框会破坏遍历顺序
考虑以下示例:Checkbox TableCell中的复选框会破坏遍历顺序,checkbox,javafx,tableview,traversal,tablecell,Checkbox,Javafx,Tableview,Traversal,Tablecell,考虑以下示例: import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.CheckBox; import javafx.scene.control.TextField; import javafx.scene.layout.HBox; import javafx.stage.Stage; public class TestCheckBoxTab extends A
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class TestCheckBoxTab extends Application {
public void start (Stage stage) {
HBox root = new HBox();
root.getChildren().addAll(new TextField(), new TextField(), new CheckBox(), new TextField());
stage.setScene(new Scene(root));
stage.show();
}
public static void main (String[] args) {
launch();
}
}
import javafx.application.Application;
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.CheckBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class AlwaysEditableTable extends Application {
public void start(Stage stage) {
TableView<ObservableList<StringProperty>> table = new TableView<>();
table.setEditable(true);
table.getSelectionModel().setCellSelectionEnabled(true);
table.setPrefWidth(505);
// Dummy columns
ObservableList<String> columns = FXCollections.observableArrayList("Column1", "Column2", "Column3", "Column4",
"Column5");
// Dummy data
ObservableList<StringProperty> row1 = FXCollections.observableArrayList(new SimpleStringProperty("Cell1"),
new SimpleStringProperty("Cell2"), new SimpleStringProperty("0"), new SimpleStringProperty("Cell4"),
new SimpleStringProperty("1"));
ObservableList<ObservableList<StringProperty>> data = FXCollections.observableArrayList();
data.add(row1);
for (int i = 0; i < columns.size(); i++) {
final int j = i;
TableColumn<ObservableList<StringProperty>, String> col = new TableColumn<>(columns.get(i));
col.setCellValueFactory(param -> param.getValue().get(j));
col.setPrefWidth(100);
if (i == 2 || i == 4) {
col.setCellFactory(e -> new CheckBoxCell(j));
} else {
col.setCellFactory(e -> new AlwaysEditingCell(j));
}
table.getColumns().add(col);
}
table.setItems(data);
Scene scene = new Scene(table);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
/**
* A cell that contains a text field that is always shown. The text of the
* text field is bound to the underlying data.
*/
public static class AlwaysEditingCell extends TableCell<ObservableList<StringProperty>, String> {
private final TextField textField;
public AlwaysEditingCell(int columnIndex) {
textField = new TextField();
this.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
if (isNowEmpty) {
setGraphic(null);
} else {
setGraphic(textField);
}
});
// The index is not changed until tableData is instantiated, so this
// ensure the we wont get a NullPointerException when we do the
// binding.
this.indexProperty().addListener((obs, oldValue, newValue) -> {
ObservableList<ObservableList<StringProperty>> tableData = getTableView().getItems();
int oldIndex = oldValue.intValue();
if (oldIndex >= 0 && oldIndex < tableData.size()) {
textField.textProperty().unbindBidirectional(tableData.get(oldIndex).get(columnIndex));
}
int newIndex = newValue.intValue();
if (newIndex >= 0 && newIndex < tableData.size()) {
textField.textProperty().bindBidirectional(tableData.get(newIndex).get(columnIndex));
setGraphic(textField);
} else {
setGraphic(null);
}
});
}
}
/**
* A cell containing a checkbox. The checkbox represent the underlying value
* in the cell. If the cell value is 0, the checkbox is unchecked. Checking
* or unchecking the checkbox will change the underlying value.
*/
public static class CheckBoxCell extends TableCell<ObservableList<StringProperty>, String> {
private final CheckBox box;
private ObservableList<ObservableList<StringProperty>> tableData;
public CheckBoxCell(int columnIndex) {
this.box = new CheckBox();
this.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
if (isNowEmpty) {
setGraphic(null);
} else {
setGraphic(box);
}
});
this.indexProperty().addListener((obs, oldValue, newValue) -> {
tableData = getTableView().getItems();
int newIndex = newValue.intValue();
if (newIndex >= 0 && newIndex < tableData.size()) {
// If active value is "1", the check box will be set to
// selected.
box.setSelected(tableData.get(getIndex()).get(columnIndex).equals("1"));
// We add a listener to the selected property. This will
// allow us to execute code every time the check box is
// selected or deselected.
box.selectedProperty().addListener((observable, oldVal, newVal) -> {
if (newVal) {
// If newValue is true the checkBox is selected, and
// we set the corresponding cell value to "1".
tableData.get(getIndex()).get(columnIndex).set("1");
} else {
// Otherwise we set it to "0".
tableData.get(getIndex()).get(columnIndex).set("0");
}
});
setGraphic(box);
} else {
setGraphic(null);
}
});
}
}
}
在这里,您可以轻松地使用TAB和SHIFT+TAB命令遍历不同的控件,并且可以正常工作
但是,如果在表视图的表单元格中有相同的控件,则复选框将打破遍历顺序。下面的示例演示了这一点:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class TestCheckBoxTab extends Application {
public void start (Stage stage) {
HBox root = new HBox();
root.getChildren().addAll(new TextField(), new TextField(), new CheckBox(), new TextField());
stage.setScene(new Scene(root));
stage.show();
}
public static void main (String[] args) {
launch();
}
}
import javafx.application.Application;
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.CheckBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class AlwaysEditableTable extends Application {
public void start(Stage stage) {
TableView<ObservableList<StringProperty>> table = new TableView<>();
table.setEditable(true);
table.getSelectionModel().setCellSelectionEnabled(true);
table.setPrefWidth(505);
// Dummy columns
ObservableList<String> columns = FXCollections.observableArrayList("Column1", "Column2", "Column3", "Column4",
"Column5");
// Dummy data
ObservableList<StringProperty> row1 = FXCollections.observableArrayList(new SimpleStringProperty("Cell1"),
new SimpleStringProperty("Cell2"), new SimpleStringProperty("0"), new SimpleStringProperty("Cell4"),
new SimpleStringProperty("1"));
ObservableList<ObservableList<StringProperty>> data = FXCollections.observableArrayList();
data.add(row1);
for (int i = 0; i < columns.size(); i++) {
final int j = i;
TableColumn<ObservableList<StringProperty>, String> col = new TableColumn<>(columns.get(i));
col.setCellValueFactory(param -> param.getValue().get(j));
col.setPrefWidth(100);
if (i == 2 || i == 4) {
col.setCellFactory(e -> new CheckBoxCell(j));
} else {
col.setCellFactory(e -> new AlwaysEditingCell(j));
}
table.getColumns().add(col);
}
table.setItems(data);
Scene scene = new Scene(table);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
/**
* A cell that contains a text field that is always shown. The text of the
* text field is bound to the underlying data.
*/
public static class AlwaysEditingCell extends TableCell<ObservableList<StringProperty>, String> {
private final TextField textField;
public AlwaysEditingCell(int columnIndex) {
textField = new TextField();
this.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
if (isNowEmpty) {
setGraphic(null);
} else {
setGraphic(textField);
}
});
// The index is not changed until tableData is instantiated, so this
// ensure the we wont get a NullPointerException when we do the
// binding.
this.indexProperty().addListener((obs, oldValue, newValue) -> {
ObservableList<ObservableList<StringProperty>> tableData = getTableView().getItems();
int oldIndex = oldValue.intValue();
if (oldIndex >= 0 && oldIndex < tableData.size()) {
textField.textProperty().unbindBidirectional(tableData.get(oldIndex).get(columnIndex));
}
int newIndex = newValue.intValue();
if (newIndex >= 0 && newIndex < tableData.size()) {
textField.textProperty().bindBidirectional(tableData.get(newIndex).get(columnIndex));
setGraphic(textField);
} else {
setGraphic(null);
}
});
}
}
/**
* A cell containing a checkbox. The checkbox represent the underlying value
* in the cell. If the cell value is 0, the checkbox is unchecked. Checking
* or unchecking the checkbox will change the underlying value.
*/
public static class CheckBoxCell extends TableCell<ObservableList<StringProperty>, String> {
private final CheckBox box;
private ObservableList<ObservableList<StringProperty>> tableData;
public CheckBoxCell(int columnIndex) {
this.box = new CheckBox();
this.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
if (isNowEmpty) {
setGraphic(null);
} else {
setGraphic(box);
}
});
this.indexProperty().addListener((obs, oldValue, newValue) -> {
tableData = getTableView().getItems();
int newIndex = newValue.intValue();
if (newIndex >= 0 && newIndex < tableData.size()) {
// If active value is "1", the check box will be set to
// selected.
box.setSelected(tableData.get(getIndex()).get(columnIndex).equals("1"));
// We add a listener to the selected property. This will
// allow us to execute code every time the check box is
// selected or deselected.
box.selectedProperty().addListener((observable, oldVal, newVal) -> {
if (newVal) {
// If newValue is true the checkBox is selected, and
// we set the corresponding cell value to "1".
tableData.get(getIndex()).get(columnIndex).set("1");
} else {
// Otherwise we set it to "0".
tableData.get(getIndex()).get(columnIndex).set("0");
}
});
setGraphic(box);
} else {
setGraphic(null);
}
});
}
}
}
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.scene.scene;
导入javafx.scene.control.CheckBox;
导入javafx.scene.control.TableCell;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableView;
导入javafx.scene.control.TextField;
导入javafx.stage.stage;
公共类AlwaysEditableTable扩展应用程序{
公众假期开始(阶段){
TableView table=新TableView();
table.setEditable(true);
table.getSelectionModel().setCellSelectionEnabled(true);
表3.setPrefWidth(505);
//虚拟柱
ObservableList columns=FXCollections.observableArrayList(“Column1”、“Column2”、“Column3”、“Column4”,
“第5栏”);
//虚拟数据
ObservableList row1=FXCollections.observableArrayList(新的SimpleStringProperty(“Cell1”),
新SimpleStringProperty(“Cell2”)、新SimpleStringProperty(“0”)、新SimpleStringProperty(“Cell4”),
新SimpleStringProperty(“1”);
ObservableList data=FXCollections.observableArrayList();
添加数据(第1行);
对于(int i=0;iparam.getValue().get(j));
列设置宽度(100);
如果(i==2 | | i==4){
col.setCellFactory(e->new CheckBoxCell(j));
}否则{
col.setCellFactory(e->new AlwaysEditingCell(j));
}
table.getColumns().add(col);
}
表2.设置项目(数据);
场景=新场景(表);
舞台场景;
stage.show();
}
公共静态void main(字符串[]args){
发射();
}
/**
*包含始终显示的文本字段的单元格
*文本字段绑定到基础数据。
*/
公共静态类AlwaysEditingCell扩展TableCell{
私有最终文本字段文本字段;
公共AlwaysEditingCell(int columnIndex){
textField=新的textField();
this.emptyProperty().addListener((obs,waspempty,isNowEmpty)->{
如果(现在为空){
设置图形(空);
}否则{
设置图形(文本字段);
}
});
//在实例化tableData之前,不会更改索引,因此
//确保在执行以下操作时不会出现NullPointerException
//绑定。
this.indexProperty().addListener((obs、oldValue、newValue)->{
ObservableList tableData=getTableView().getItems();
int oldIndex=oldValue.intValue();
如果(oldIndex>=0&&oldIndex=0&&newIndex{
如果(现在为空){
设置图形(空);
}否则{
设置图形(框);
}
});
this.indexProperty().addListener((obs、oldValue、newValue)->{
tableData=getTableView().getItems();
int newIndex=newValue.intValue();
如果(newIndex>=0&&newIndex{
if(newVal){
//如果newValue为true,则选中复选框,并且
//我们将相应的单元格值设置为“1”。
tableData.get(getIndex()).get(columnIndex).set(“1”);
}否则{
//否则,我们将其设置为“0”。
tableData.get(getIndex()).get(columnIndex).set(“0”);
}
});
设置图形(框);
}否则{
设置图形(空);