JavaFX 8自定义ListView单元格it';这是邪恶的
我有自定义ListView单元格我有带两个控件的HBox:JavaFX 8自定义ListView单元格it';这是邪恶的,listview,javafx,javafx-8,Listview,Javafx,Javafx 8,我有自定义ListView单元格我有带两个控件的HBox: 带有名称字段的标签 它必须从对象的上下文生成 例如,我设置了类字段的ListView项数组、if field type Boolean i create复选框、if String i create TextField等 问题是:我只能在updateItem()方法中获取字段对象,并且只有在那里我才能创建控件 在JavaFX7中,一切都很好,但在Java8中,我看不到我的控件 解决我的案子的方法正确吗 更新1 下面是复制问题的完整示例:
package javafx8listviewexample;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Date;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.DatePicker;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.util.Callback;
/**
*
* @author dmitrynelepov
*/
public class FXMLDocumentController implements Initializable {
static class TestClassForListView {
public String fieldString;
public Date fieldDate;
}
static class MyListCell extends ListCell<Field> {
/**
* As in tutorial
*
* @param t
* @param bln
*/
@Override
protected void updateItem(Field t, boolean bln) {
super.updateItem(t, bln);
if (t != null) {
if (t.getType().equals(String.class)) {
System.out.println("Draw string");
setGraphic(new TextField(t.getName()));
} else if (t.getType().equals(Date.class)) {
System.out.println("Draw Date");
setGraphic(new DatePicker());
}
}
}
}
@FXML
private ListView<Field> listView;
@FXML
private void handleButtonAction(ActionEvent event) {
this.listView.getItems().clear();
this.listView.setItems(
FXCollections.observableArrayList(
TestClassForListView.class.getFields()
)
);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
this.listView.setCellFactory(new Callback<ListView<Field>, ListCell<Field>>() {
@Override
public ListCell<Field> call(ListView<Field> p) {
return new MyListCell();
}
});
}
}
PackageJavaFX8ListViewExample;
导入java.lang.reflect.Field;
导入java.net.URL;
导入java.util.Date;
导入java.util.ResourceBundle;
导入javafx.collections.FXCollections;
导入javafx.event.ActionEvent;
导入javafx.fxml.fxml;
导入javafx.fxml.Initializable;
导入javafx.scene.control.DatePicker;
导入javafx.scene.control.ListCell;
导入javafx.scene.control.ListView;
导入javafx.scene.control.TextField;
导入javafx.scene.control.cell.TextFieldListCell;
导入javafx.util.Callback;
/**
*
*@作者dmitrynelepov
*/
公共类FXMLDocumentController实现可初始化{
静态类TestClassForListView{
公共字符串字段字符串;
公共日期字段日期;
}
静态类MyListCell扩展了ListCell{
/**
*就像在教程中一样
*
*@param t
*@param bln
*/
@凌驾
受保护的void updateItem(字段t,布尔bln){
超级更新项(t,bln);
如果(t!=null){
if(t.getType().equals(String.class)){
System.out.println(“绘制字符串”);
setGraphic(新的文本字段(t.getName());
}else如果(t.getType().equals(Date.class)){
系统输出打印号(“提取日期”);
setGraphic(新的日期选择器());
}
}
}
}
@FXML
私有列表视图列表视图;
@FXML
私有无效把手按钮操作(ActionEvent事件){
this.listView.getItems().clear();
this.listView.setItems(
FXCollections.observableArrayList(
TestClassForListView.class.getFields()
)
);
}
@凌驾
公共void初始化(URL、ResourceBundle rb){
this.listView.setCellFactory(新的回调函数(){
@凌驾
公共ListCell调用(ListView p){
返回新的MyListCell();
}
});
}
}
这里是程序JDK 7的屏幕截图
正如你所看到的,文本字段可以被聚焦和编辑
但是如果我用JDK 8运行这个例子,我得到
在这里,您可以看到文本字段无法聚焦和编辑。看起来您需要一个控件fx:
一个类似的实现,在对的回答中。尽管该问题的答案基于TableView,但ListView和TableView都是虚拟化控件,因此实现概念有点类似于使用问题中概述的带HBox的ListView
根据问题中的示例代码进行更新 我仍然认为ControlsFX PropertySheet似乎是您试图实现的最合适的解决方案。为此类任务使用虚拟化控件(如ListView)只会使事情变得更加复杂 基于ListView的属性编辑器的完整解决方案非常复杂,超出了StackOverflow答案中合理提供的范围 您在问题中提供的示例代码存在一些问题。ListView是一个虚拟化控件,因此您不应该在调用update时创建新的图形节点来放置在ListView中。发生的情况是,一个TextField获得焦点,然后在ListView上调用update,然后创建一个新的TextField,默认情况下,新的TextField没有焦点 我认为ListView本身对于您的特定情况有一些实现问题,并且调用update的次数太多。不管怎样,您应该编写代码,以便能够适当地处理在单个单元格上多次调用的更新,并进行修改。如果您这样做,ListView调用您的方法的次数是否超过它需要的次数就无关紧要了 下面是一些示例代码,可以帮助您取得更大的进步。我不认为示例代码是您问题的完整解决方案,它当然不是作为Java对象的综合属性编辑器提供的,但它可能会给您一些灵感,帮助您改进和实现代码(假设您决定继续尝试以这种方式解决此问题)。如果继续使用ListView,可能需要查看ListView的编辑例程(类似于Oracle JavaFX教程中的定义)
导入javafx.application.application;
导入javafx.beans.value.ChangeListener;
导入javafx.collections.FXCollections;
导入javafx.scene.scene;
导入javafx.scene.control.*;
导入javafx.stage.stage;
导入java.lang.reflect.Field;
导入java.time.LocalDate;
/**
*@作者dmitrynelepov
*由Jewelsea修改
*/
公共类已生存扩展应用程序{
静态类TestClassForListView{
公共字符串字段字符串;
公共LocalDate字段日期;
@凌驾
公共字符串toString(){
返回“TestClassForListView{”+
“fieldString='”+fieldString+'\''+
“,fieldDate=“+fieldDate+
'}';
}
}
静态类MyListCell扩展了ListCell{
私有文本字段文本字段;
私人日期选择器日期选择器;
私有对象编辑对象;
私有ChangeListener editCommitHandler;
公共MyListCell(Obj
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;
import java.lang.reflect.Field;
import java.time.LocalDate;
/**
* @author dmitrynelepov
* Modified by Jewelsea
*/
public class EvilHasSurvived extends Application {
static class TestClassForListView {
public String fieldString;
public LocalDate fieldDate;
@Override
public String toString() {
return "TestClassForListView{" +
"fieldString='" + fieldString + '\'' +
", fieldDate=" + fieldDate +
'}';
}
}
static class MyListCell extends ListCell<Field> {
private TextField textField;
private DatePicker datePicker;
private Object editedObject;
private ChangeListener<Boolean> editCommitHandler;
public MyListCell(Object editedObject) {
this.editedObject = editedObject;
setContentDisplay(ContentDisplay.RIGHT);
}
@Override
protected void updateItem(Field t, boolean bln) {
super.updateItem(t, bln);
if (datePicker != null) {
datePicker.focusedProperty().removeListener(editCommitHandler);
}
if (textField != null) {
textField.focusedProperty().removeListener(editCommitHandler);
}
if (t == null) {
setText(null);
setGraphic(null);
return;
}
if (t.getType().equals(String.class)) {
if (textField == null) {
textField = new TextField();
}
editCommitHandler = (observable, oldValue, newValue) -> {
try {
t.set(editedObject, textField.getText());
System.out.println(editedObject + " for " + textField + " value " + textField.getText());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
};
textField.focusedProperty().addListener(editCommitHandler);
setText(t.getName());
setGraphic(textField);
} else if (t.getType().equals(LocalDate.class)) {
if (datePicker == null) {
datePicker = new DatePicker();
}
editCommitHandler = (observable, oldValue, newValue) -> {
try {
t.set(editedObject, datePicker.getValue());
System.out.println(editedObject + " for " + datePicker + " value " + datePicker.getValue());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
};
datePicker.focusedProperty().addListener(editCommitHandler);
setText(t.getName());
setGraphic(datePicker);
}
}
}
@Override
public void start(Stage stage) throws Exception {
ListView<Field> listView = new ListView<>();
listView.setItems(
FXCollections.observableArrayList(
TestClassForListView.class.getFields()
)
);
TestClassForListView testObject = new TestClassForListView();
listView.setCellFactory(p -> new MyListCell(testObject));
stage.setScene(new Scene(listView));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}