[附全源代码]
我有一个包含3列的javafx TableView(“名称”,“性别”,“国家/地区”)。我正在将细胞工厂附加到我的所有栏目中。如下所示。
nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
genderCol.setCellFactory(ComboBoxTableCell.forTableColumn(GenderEnum.values()));
countryCol.setCellFactory(ComboBoxTableCell.forTableColumn("India", "USA"));
我没有自己实现任何提交逻辑。现在我更改所有3列中的值,然后打印数据。我能够在除genderCol之外的所有列上看到更改的值。关于该列的唯一区别是它使用枚举。
当我更改countryCol(也是ComoboBoxTableCell)中的值时,countryProperty首先使用旧值调用两次,然后使用新值调用,但对于genderCol,genderProperty仅调用一次。
您可以复制并执行代码,首先打印数据而不更改任何内容,然后更改所有3列上的值,然后打印数据。现在检查,除了genderCol,其他列的值已更改。
我遗漏了任何内容或对枚举做错了什么
Main.java
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application
{
@Override
public void start(final Stage primaryStage)
{
try
{
final VBox root = FXMLLoader.load(this.getClass().getResource("MainView.fxml"));
final Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
catch(final Exception e)
{
e.printStackTrace();
}
}
public static void main(final String[] args)
{
launch(args);
}
}
MainView.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<VBox spacing="10.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<children>
<TableView fx:id="table" editable="true">
<columns>
<TableColumn prefWidth="100.0" text="Name" fx:id="nameCol">
<cellValueFactory><PropertyValueFactory property="name" /></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="100.0" text="Gender" fx:id="genderCol">
<cellValueFactory><PropertyValueFactory property="gender" /></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="100.0" text="Country" fx:id="countryCol">
<cellValueFactory><PropertyValueFactory property="country" /></cellValueFactory>
</TableColumn>
</columns>
</TableView>
<Button text="Print Data" onAction="#printData"/>
</children>
</VBox>
MainController.java
package application;
import java.net.URL;
import java.util.ResourceBundle;
import application.Person.GenderEnum;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
/**
* @author Saravana Kumar M
*
*/
public class MainController implements Initializable
{
@FXML
TableView<Person> table;
@FXML
TableColumn<Person, String> nameCol;
@FXML
TableColumn<Person, GenderEnum> genderCol;
@FXML
TableColumn<Person, String> countryCol;
@Override
public void initialize(final URL location, final ResourceBundle resources)
{
this.nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
this.genderCol.setCellFactory(ComboBoxTableCell.forTableColumn(GenderEnum.values()));
this.countryCol.setCellFactory(ComboBoxTableCell.forTableColumn("India", "USA"));
final Person p1 = new Person("A", "M", "India");
final Person p2 = new Person("B", "F", "USA");
final Person p3 = new Person("C", "N", "India");
final Person p4 = new Person("D", null, "USA");
final Person p5 = new Person("E", "M", "India");
final Person p6 = new Person("F", "F", "USA");
final Person p7 = new Person("G", "N", "India");
final Person p8 = new Person("H", null, "USA");
this.table.setItems(FXCollections.observableArrayList(p1, p2, p3, p4, p5, p6, p7, p8));
this.genderCol.setOnEditCommit((event) -> this.doThis(event));
}
private void doThis(final CellEditEvent<Person, GenderEnum> event)
{
System.out.println(event);
System.out.println(event.getOldValue());
System.out.println(event.getNewValue());
System.out.println(event.getRowValue());
}
@FXML
public void printData()
{
this.table.getItems().forEach(System.out::println);
}
}
Person.java
package application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
/**
* @author Saravana Kumar M
*
*/
public class Person
{
private final StringProperty name;
private final ObjectProperty<GenderEnum> gender;
private final StringProperty country;
public Person(final String name, final String gender, final String country)
{
this.name = new SimpleStringProperty(name);
if(gender == null)
{
this.gender = new SimpleObjectProperty<>();
}
else
{
this.gender = new SimpleObjectProperty<>(GenderEnum.valueOf(gender));
}
this.country = new SimpleStringProperty(country);
}
public String getName()
{
return this.name.get();
}
public void setName(final String name)
{
this.name.set(name);
}
public StringProperty nameProperty()
{
return this.name;
}
public GenderEnum getGender()
{
return this.gender.get();
}
public void setGender(final GenderEnum gender)
{
this.gender.set(gender);
}
public ObjectProperty<GenderEnum> genderProperty()
{
return this.gender;
}
public String getCountry()
{
return this.country.get();
}
public void setCountry(final String country)
{
this.country.set(country);
}
public StringProperty countryProperty()
{
return this.country;
}
@Override
public String toString()
{
return "name : " + this.name + " name.get : " + this.name.get() + " gender : " + this.gender + " gender.get : " + this.gender.get() + " country : " + this.country.get() + " country.get : " + this.country.get();
}
public enum GenderEnum
{
M("Male"), F("Female"), N("None");
private final String label;
private GenderEnum(final String label)
{
this.label = label;
}
@Override
public String toString()
{
return this.label;
}
}
}
先谢谢。
答案 0 :(得分:2)
默认情况下,TableColumn编辑提交处理程序为非null,带有 尝试覆盖的属性值的默认处理程序 当前正在编辑的行中的项目。它可以做到这一点
Cell.commitEdit(Object)
方法在新值中传递,这是 通过CellEditEvent
传递给编辑提交处理程序 被解雇。这只是一个呼唤的问题TableColumn.CellEditEvent.getNewValue()
要检索此值。非常重要的是要注意,如果你打电话
TableColumn.setOnEditCommit(javafx.event.EventHandler)
与您自己EventHandler
,然后您将删除默认处理程序。除非 然后处理对属性的回写(或相关数据) 来源),什么都不会发生。您可以使用以下方法解决此问题TableColumnBase.addEventHandler(javafx.event.EventType, javafx.event.EventHandler)
方法添加 带有所需EventHandler的TableColumn.EDIT_COMMIT_EVENT
EventType 作为第二个论点。使用此方法,您将不会替换 默认实现,但在编辑提交时会通知您 已经发生了。
因为你有
this.genderCol.setOnEditCommit((event) -> this.doThis(event));
在控制器类中,删除更新属性的默认处理程序。如果用
替换它 this.genderCol.addEventHandler(TableColumn.<Person, GenderEnum>editCommitEvent(),
event -> this.doThis(event));
它将按预期工作。 (注意文档在告诉您如何获取事件类型时不正确。另请注意,您的处理程序将在默认值之前调用,因此getRowValue()
的输出将在更新之前显示值 ,但按下按钮显示值将给出新值。)