gpt4 book ai didi

listview - JavaFX 8 自定义 ListView Cells it's Evil

转载 作者:行者123 更新时间:2023-12-04 07:02:55 24 4
gpt4 key购买 nike

我有自定义 ListView 单元格我有两个控件的 HBox:

  • 带有名称字段的标签
  • 它必须从对象
  • 的上下文中生成

    例如,我设置类字段的 ListView 项目数组,如果字段类型为 bool 值,我创建复选框,如果字符串我创建文本字段等。

    问题是:我只在方法 updateItem() 中获得 Field 对象 - 只有在那里我才能创建我的控件。

    在 JavaFX 7 中一切正常,但在 Java 8 上 - 我看不到我的控件。

    是否存在解决我的案例的正确方法?

    更新 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();
    }
    });

    }

    }

    这里是程序 JDK 7 的截图

    enter image description here

    如您所见,我可以聚焦和编辑 TextField。

    但是如果我用 JDK 8 运行这个例子,我得到了

    enter image description here

    在这里你可以看到 TextField 无法聚焦和编辑。

    最佳答案

    看起来您想要 ControlsFX PropertySheet :

    propertysheet

    类似的实现,是对 JavaFX 2 TableView : different cell factory depending on the data inside the cell 的回答。 .即使该问题的答案是基于 TableView,ListView 和 TableView 虚拟化控件,因此实现概念有点类似于使用带有 HBox 的 ListView,如您的问题所述。

    tableproperty

    根据问题中的示例代码进行更新。

    我仍然认为 ControlsFX PropertySheet 似乎是最适合您要完成的任务的解决方案。使用像 ListView 这样的虚拟控件来完成这样的任务只会让事情变得比他们需要的更复杂。

    基于 ListView 的属性编辑器的完整解决方案是一件非常复杂的事情,超出了 StackOverflow 答案中可以合理提供的范围。

    您在问题中提供的示例代码存在一些问题。 ListView 是一个虚拟化控件,因此您不应在调用更新时始终创建新的图形节点以放置在 ListView 中。发生的情况是 TextField 获得焦点,然后在 ListView 上调用 update 并创建一个新的 TextField 并且默认情况下新的 TextField 没有焦点。

    我认为 ListView 本身对于您的特定情况有一些实现问题,并且多次调用 update 。无论如何,您应该编写您的代码,以便您可以适本地处理在单个单元格上多次调用的更新和。如果您这样做,则 ListView 调用您的方法的次数是否超过它需要的次数都没有关系。

    这是一些示例代码,可以帮助您取得更多进展。我不认为示例代码是您问题的完整解决方案,它当然不是作为 Java 对象的综合属性编辑器提供的,但也许它可能会给您一些灵感来帮助改进和实现您的代码(假设您决定继续尝试以这种方式解决这个问题)。如果您继续使用 ListView,您可能需要查看 ListView 的编辑例程(类似于 Oracle JavaFX 教程中为 editing table cells 定义的内容)。

    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);
    }
    }

    关于listview - JavaFX 8 自定义 ListView Cells it's Evil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19977600/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com