Java 更新TableColumn单元格中的值时出现问题

Java 更新TableColumn单元格中的值时出现问题,java,javafx,Java,Javafx,我的问题有点模棱两可(我不知道这是不是一个bug),我希望用户输入他想要的任何值,只要它不是空的,所以我创建了一个方法来检查输入,如果输入字符串是空的,则返回上一个值,如果用户清除单元格并按下enter键,这就是问题发生的地方,该单元格不显示任何内容,直到我单击它,以下是我的项目的功能示例: import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.TableColu

我的问题有点模棱两可(我不知道这是不是一个bug),我希望用户输入他想要的任何值,只要它不是空的,所以我创建了一个方法来检查输入,如果输入字符串是空的,则返回上一个值,如果用户清除单元格并按下enter键,这就是问题发生的地方,该单元格不显示任何内容,直到我单击它,以下是我的项目的功能示例:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class Launcher extends Application
{

    @Override
    public void start(Stage stage) throws Exception
    {
        AnchorPane root = new AnchorPane();

        TableView<Apprenant> table = new TableView<>();
        table.setPrefWidth(800);
        table.setEditable(true);
        
        TableColumn<Apprenant, String> nom = new TableColumn<>("Noms");
        nom.setPrefWidth(100);
        
        TableColumn<Apprenant, String> prenom = new TableColumn<>("Prenoms");
        prenom.setPrefWidth(100);

        nom.setCellValueFactory(var -> var.getValue().nomProperty());
        prenom.setCellValueFactory(var -> var.getValue().prenomProperty());
        
        nom.setCellFactory(TextFieldTableCell.forTableColumn());
        nom.setOnEditCommit((CellEditEvent<Apprenant, String> evt)->{
            
            Apprenant app = table.getSelectionModel().getSelectedItem();
            app.setNom(check(evt.getNewValue(),app.nomProperty().get()));
    
            /*THE ONLY WAY TO DISPLAY THE UPDATED VALUE*/
            //nom.setVisible(false); 
            //nom.setVisible(true);
        });

        table.getColumns().add(nom);
        table.getColumns().add(prenom);
        table.getItems().add(new Apprenant("monNom","monPrenom"));

        root.getChildren().add(table);
        
        Scene scene = new Scene(root,1200,800);
        stage.setScene(scene);
        stage.show();
    }
    
    private static String check(String valeur,String prev)
    {
        if(valeur.isEmpty())
        {   
            return prev;
        }
        else
        {
            return valeur;
        }
    }
    
    public static void main(String[] args)
    {
        launch(args);
    }
}

因此,我的问题很简单,如何更新单元格而不必使用上述
setVisible
方法或
updateItem
函数?我发现这个主题与我的主题有些相似,但没有提及我的问题。

JavaFX中虚拟化控件的编辑机制有些不透明

与其捕获提交编辑后发生的
editCommit
事件,不如覆盖单元格的
committedit()
方法:

        nom.setCellFactory(tc -> new TextFieldTableCell<>(TextFormatter.IDENTITY_STRING_CONVERTER) {
            @Override
            public void commitEdit(String newValue) {
                if (newValue.isEmpty()) {
                    cancelEdit();
                } else {
                    super.commitEdit(newValue);
                }
            }
        });
//        nom.setCellFactory(TextFieldTableCell.forTableColumn());
//        nom.setOnEditCommit((CellEditEvent<Apprenant, String> evt)->{
//            
//            Apprenant app = table.getSelectionModel().getSelectedItem();
//            app.setNom(check(evt.getNewValue(),app.getNom().get()));
//    
//            /*THE ONLY WAY TO DISPLAY THE UPDATED VALUE*/
//            //nom.setVisible(false); 
//            //nom.setVisible(true);
//        });
nom.setCellFactory(tc->new TextFieldTableCell(TextFormatter.IDENTITY\u STRING\u转换器){
@凌驾
public void committedit(字符串newValue){
if(newValue.isEmpty()){
取消编辑();
}否则{
super.committedit(newValue);
}
}
});
//nom.setCellFactory(TextFieldTableCell.forTableColumn());
//名称setOnEditCommit((CellEditEvent evt)->{
//            
//Apprenant app=table.getSelectionModel().getSelectedItem();
//app.setNom(检查(evt.getNewValue(),app.getNom().get());
//    
///*显示更新值的唯一方法*/
////名称setVisible(false);
////nom.setVisible(true);
//        });

这可能被认为是一种黑客行为,因为验证数据实际上不是细胞的工作,但考虑到API,这可能是阻力最小的途径。“正确”的方法可能是在模型中执行验证,这(据我所知)将涉及子类化
StringPropertyBase
,以支持验证。

无关:请使用属性命名模式。例如,您应该有
StringProperty nomProperty()
String getNom()
,还有
void setNom(String nom)
@kleopatra,像这样吗?我不熟悉约定:)根据设计,提交处理程序是实现接受或拒绝类型的验证的方法——无可否认,这并不太灵活。不显示编辑后的值是一个错误,无论是在OPs代码中(对所选项目而不是通过事件传递的状态进行操作的奇怪实现),还是在fx中(隐约记得一些问题,现在已经太晚了,无法挖掘)
        nom.setCellFactory(tc -> new TextFieldTableCell<>(TextFormatter.IDENTITY_STRING_CONVERTER) {
            @Override
            public void commitEdit(String newValue) {
                if (newValue.isEmpty()) {
                    cancelEdit();
                } else {
                    super.commitEdit(newValue);
                }
            }
        });
//        nom.setCellFactory(TextFieldTableCell.forTableColumn());
//        nom.setOnEditCommit((CellEditEvent<Apprenant, String> evt)->{
//            
//            Apprenant app = table.getSelectionModel().getSelectedItem();
//            app.setNom(check(evt.getNewValue(),app.getNom().get()));
//    
//            /*THE ONLY WAY TO DISPLAY THE UPDATED VALUE*/
//            //nom.setVisible(false); 
//            //nom.setVisible(true);
//        });