英文:
Problem with updating value in TableColumn Cell
问题
问题有点模糊(我不确定是否是一个bug),我希望用户可以输入任何值,只要不是空的,所以我创建了一个方法来检查输入,如果输入字符串为空,则返回先前的值,这就是问题出现的地方,如果用户清除单元格并按下回车键,单元格不会显示任何内容,直到我点击它,以下是我的项目的功能示例:
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()));
});
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);
}
}
模型:
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Apprenant {
private StringProperty nom = new SimpleStringProperty();
private StringProperty prenom = new SimpleStringProperty();
public Apprenant(String nom, String prenom) {
this.nom.set(nom);
this.prenom.set(prenom);
}
public StringProperty nomProperty() {
return nom;
}
public StringProperty prenomProperty() {
return prenom;
}
public void setNom(String nom) {
this.nom.set(nom);
}
public void setPrenom(String prenom) {
this.prenom.set(prenom);
}
}
所以我的问题很简单,如何在不使用上面提到的setVisible
方法或updateItem
函数的情况下更新单元格?我发现这个主题与我的问题有些类似,但没有提到我的问题。
英文:
My problem is a bit ambiguous (I don't know if it's a bug or not), i want the user to enter any value he wants, as long as it's not empty, so i created a method to check the input which returns the previous value if the input string is empty, and this is where the problem occurs, if the user clears the cell and presses the enter key, the cell displays nothing, until I click on it, here's a functional example of my project :
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);
}
}
The model :
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Apprenant
{
private StringProperty nom = new SimpleStringProperty();
private StringProperty prenom = new SimpleStringProperty();
public Apprenant(String nom, String prenom)
{
this.nom.set(nom);
this.prenom.set(prenom);
}
public StringProperty nomProperty()
{
return nom;
}
public StringProperty prenomProperty()
{
return prenom;
}
public void setNom(String nom)
{
this.nom.set(nom);
}
public void setPrenom(String prenom)
{
this.prenom.set(prenom);
}
}
So my question is simple, how to update the cell without having to use the setVisible
method as indicated above or the updateItem
function ? I found this topic somewhat similar to mine but without any reference to my problem.
答案1
得分: 1
JavaFX中用于虚拟控件的编辑机制有些不透明...
不要捕获editCommit
事件,该事件发生在编辑已提交之后,而是重写单元格的commitEdit()
方法:
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);
// });
这可能被视为一种技巧,因为验证数据不是单元格的真正工作,但考虑到API,这可能是最简单的方法。"正确"的做法可能是在模型中执行验证,这将涉及子类化StringPropertyBase
以支持验证(就我所见)。
英文:
The editing mechanisms for virtualized controls in JavaFX are somewhat opaque...
Instead of capturing the editCommit
event, which happens after an edit has been committed, override the commitEdit()
method of the cell:
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);
// });
This might be considered something of a hack, as it's not really the cell's job to validate data, but it's probably the path of least resistance given the API. The "correct" way to do this would probably be to perform the validation in the model, which (as far as I can see) would involve subclassing StringPropertyBase
to support the validation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论