我正在尝试在 javafx 中实现 TreeTableView,其中第一列包含字符串值,第三列将呈现为三态复选框。使用以下 MCVE,我可以获得一个树表,但复选框中的所有选择都不会在父折叠/展开或调整表大小时持续存在。
MCVE
A 类是父级。
B 类扩展 A 并且是子类。
C 类代表第二列,(呈现为复选框)
MVCECheckBox 类构建树表并显示它。
爪哇
package mcve.checkbox;
import java.util.List;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
/**
*
* @author returncode13
*/
public class A {
StringProperty name=new SimpleStringProperty();
C check=new C();
List<A> children;
public StringProperty getName() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public C getCheck() {
return check;
}
public void setCheck(C check) {
this.check = check;
}
public StringProperty nameProperty(){
return name;
}
public List<A> getChildren() {
return children;
}
public void setChildren(List<A> children) {
this.children = children;
}
}
B.java
package mcve.checkbox;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
/**
*
* @author returncode13
*/
public class B extends A{
StringProperty name=new SimpleStringProperty();
C Check=new C();
@Override
public StringProperty getName() {
return name;
}
@Override
public void setName(String name) {
this.name.set(name);
}
@Override
public C getCheck() {
return Check;
}
@Override
public void setCheck(C Check) {
this.Check = Check;
}
@Override
public StringProperty nameProperty(){
return name;
}
}
C.java
package mcve.checkbox;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
/**
*
* @author returncode13
*/
public class C {
BooleanProperty checkUncheck=new SimpleBooleanProperty();
BooleanProperty indeterminate=new SimpleBooleanProperty();
public BooleanProperty getCheckUncheck() {
return checkUncheck;
}
public void setCheckUncheck(BooleanProperty checkUncheck) {
this.checkUncheck = checkUncheck;
}
public BooleanProperty getIndeterminate() {
return indeterminate;
}
public void setIndeterminate(BooleanProperty indeterminate) {
this.indeterminate = indeterminate;
}
public BooleanProperty checkUncheckProperty(){
return checkUncheck;
}
public BooleanProperty indeterminateProperty(){
return indeterminate;
}
}
MCVECheckBox.java
package mcve.checkbox;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
*
* @author returncode13
*/
public class MCVECheckBox extends Application {
A selectedItem;
private TreeTableView<A> treetable=new TreeTableView<>();
@Override
public void start(Stage primaryStage) {
//setting up parents (A) and children (B)
A a1=new A();
a1.setName("A1");
List<A> A1Children=new ArrayList();
B b11=new B();
b11.setName("B11");
B b12=new B();
b12.setName("B12");
A1Children.add(b11);
A1Children.add(b12);
a1.setChildren(A1Children);
A a2=new A();
a2.setName("A2");
List<A> A2Children=new ArrayList();
B b21=new B();
b21.setName("B21");
B b22=new B();
b22.setName("B22");
A2Children.add(b21);
A2Children.add(b22);
a2.setChildren(A2Children);
//tree columns . first one holds strings
TreeTableColumn<A,String> name=new TreeTableColumn<>("Name");
name.setCellValueFactory(new TreeItemPropertyValueFactory<>("name"));
//2nd tree columns. rendered as checkboxes. boolean values
TreeTableColumn<A,Boolean> checks=new TreeTableColumn<>("Checks");
checks.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<A, Boolean>, ObservableValue<Boolean>>() {
@Override
public ObservableValue<Boolean> call(TreeTableColumn.CellDataFeatures<A, Boolean> param) {
A a=param.getValue().getValue();
SimpleBooleanProperty checkUncheck=new SimpleBooleanProperty();
SimpleBooleanProperty indeterminate=new SimpleBooleanProperty();
checkUncheck=(SimpleBooleanProperty) a.getCheck().getCheckUncheck();
indeterminate=(SimpleBooleanProperty) a.getCheck().getIndeterminate();
//to do: set parents status based on children status.
if(indeterminate.get()){
return indeterminate;
}else{
return checkUncheck;
}
}
});
checks.setCellFactory(new Callback<TreeTableColumn<A, Boolean>, TreeTableCell<A, Boolean>>() {
@Override
public TreeTableCell<A, Boolean> call(TreeTableColumn<A, Boolean> param) {
return new CheckBoxCell();
}
});
//building the tree;
TreeItem<A> a1item=new TreeItem<>(a1);
TreeItem<A> b11item=new TreeItem<>(b11);
TreeItem<A> b12item=new TreeItem<>(b12);
a1item.getChildren().add(b11item);
a1item.getChildren().add(b12item);
TreeItem<A> a2item=new TreeItem<>(a2);
TreeItem<A> b21item=new TreeItem<>(b21);
TreeItem<A> b22item=new TreeItem<>(b22);
a2item.getChildren().add(b21item);
a2item.getChildren().add(b22item);
TreeItem<A> root=new TreeItem<>();
root.getChildren().add(a1item);
root.getChildren().add(a2item);
treetable.getColumns().addAll(name,checks);
treetable.setRoot(root);
treetable.setShowRoot(false);
treetable.setEditable(true);
// StackPane rootSp = new StackPane();
Scene scene = new Scene(treetable, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
//to render checkboxes in treetable
private class CheckBoxCell extends TreeTableCell<A, Boolean> {
CheckBox checkbox;
public CheckBoxCell() {
checkbox=new CheckBox();
checkbox.setAllowIndeterminate(true);
checkbox.selectedProperty().addListener((obs,wasSelected,isNowSelected) -> {
if(isNowSelected){
selectedItem=getTreeTableRow().getItem();
}
});
}
@Override
public void updateItem(Boolean b,boolean empty){
super.updateItem(b, empty);
if(empty){
setGraphic(null);
}else{
checkbox.setSelected(b);
setGraphic(checkbox);
}
}
}
}
我之前曾尝试使用 CheckTreeTableCell 在第二列上设置单元格工厂,但很快发现 CheckTreeTableCell 不支持三态(选中、取消选中、不确定)复选框。之后我尝试实现上述代码。尽管我能够引入三态复选框,但我无法让它们的状态持续存在。每次折叠/展开父级时,对其子级所做的检查将变为未选中状态。
感谢您对确定修复程序的任何帮助。