2013-11-14 30 views
7

我有定制的ListView小区i具有HBox中有两个对照:JavaFX的8自定义的ListView细胞是恶

  1. 标签与名称字段
  2. 这是从对象

的上下文例如产生绝我设置类字段的Lis​​tView的条目数组,如果场类型布尔我创建复选框,如果字符串我创建TextField和等

问题是:我只在方法的updateItem得到Field对象() - 只有我可以创建我的控件。

在JavaFX 7一切工作正常,但Java的8 - 我没有看到我的控制。

是存在的,解决我的情况下,正确的方法是什么?

UPDATE 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

如u可以看到我的TextField可以聚焦并编辑。

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

​​

这里可以看出U文本字段不能集中和编辑。

+0

用于复制问题的完整最小代码对于分析非常重要。如果您需要进一步协助您的特定实施,并希望有人调查并解释为什么它不起作用,那么您需要放置代码以将编辑的问题复制为[SSCCE](http://sscce.org) )。 – jewelsea

+2

虽然这个问题非常有用,可否请更新标题?它应该更准确地反映你对javafx8中自定义的ListCell对象的看法。 – demongolem

回答

10

看起来像你想有一个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上调用更新,并创建一个新的TextField,并且默认情况下新的TextField不具有焦点。

我认为ListView本身对于您的特定情况有一些实现问题,并且调用更新次数太多。无论如何,您应该编写代码,以便您可以在单个单元格上适当地处理多次调用的更新。如果你这样做,如果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); 
    } 
} 
+0

这不正确,我需要和updateItem模型工作不同的TableView updateItem。您会看到:当您创建TableView Cell时,它是完整的事件,但是如果在ListView上作为子节点控件执行相同的操作 - 则会重复调用Update。 –

+0

请在您的问题中发布您的代码。 – jewelsea

+0

更新问题:你可以看到 - 在updateItem中 - 我使用与u相同的setGraphics方法。 –

相关问题