Combobox javafx2 tableview问题:单元格中的回调和可编辑组合框

Combobox javafx2 tableview问题:单元格中的回调和可编辑组合框,combobox,callback,javafx,tableview,Combobox,Callback,Javafx,Tableview,我对tableview及其单元格有问题。我想用可编辑的组合框自定义单元格。下面是我的组合框代码: public class CbbxEditSuppr extends ComboBox<BoxItem> { private TextField editor = null; private ObservableList<BoxItem> items = null; private double prefWidth = 0.0; /** * Constructeur

我对tableview及其单元格有问题。我想用可编辑的组合框自定义单元格。下面是我的组合框代码:

public class CbbxEditSuppr extends ComboBox<BoxItem> {

private TextField editor = null;
private ObservableList<BoxItem> items = null;

private double prefWidth = 0.0;


/**
 * Constructeur.
 * 
 * @param addedItems ObservableList<String>
 * @param prefWidth double largeur préférée
 */
public CbbxEditSuppr(ObservableList<String> addedItems, final double prefWidth) {
    // initialisation des attributs
    editor = this.getEditor();
    items = this.getItems();
    this.prefWidth = prefWidth;
    this.setPrefWidth(prefWidth);
    // initialisation du contenu de la cellule
    this.setCellFactory(new Callback<ListView<BoxItem>, ListCell<BoxItem>>() {
        @Override
        public ListCell<BoxItem> call(ListView<BoxItem> p) {
            final ListCell<BoxItem> cell = new ListCell<BoxItem>() {
                @Override
                protected void updateItem(BoxItem t, boolean bln) {
                    super.updateItem(t, bln);
                    if (t != null) {
                        setGraphic(t);
                    } else {
                        setGraphic(null);
                    }
                }
            };
            return cell;
        }
    });
    // déininition du converter
    this.setConverter(new StringConverter<BoxItem>() {
        @Override
        public String toString(BoxItem cbbx) {
            if (cbbx == null) {
                return null;
            } else {
                return cbbx.getName();
            }
        }


        @Override
        public BoxItem fromString(String id) {
            if (id != null) {
                final BoxItem box = new BoxItem(id, items, prefWidth);
                return box;
            } else {
                return null;
            }

        }
    });
    /* ajout des valeurs a la liste d'items */
    if (addedItems != null && addedItems.size() > 0) {
        for (String stg : addedItems) {
            if (stg != null) {
                final BoxItem hbox = new BoxItem(stg, items, this.prefWidth);
                items.add(hbox);
            }
        }
    }
    // permet de prendre en compte la touche ENTER, et ajouter des valeurs a la liste
    this.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
        public void handle(final KeyEvent event) {
            if (event != null && event.getCode().equals(KeyCode.ENTER)) {
                if (editor.getText().trim().length() > 0) {
                    addItem(editor.getText(), prefWidth);
                    editor.clear();
                }
            }
        }
    });
    // propriétés editable et selection du premier element
    this.setEditable(true);
    this.getSelectionModel().selectFirst();
    // ajout de l'affichage du menu popup lors du focus du textfield d'edition de la combobox
    editor.focusedProperty().addListener(new ChangeListener<Boolean>() {
        @Override
        public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) {
            if (arg0 != null && arg2) {
                showpopupMenu();
            }
        }
    });
}


/**
 * Permet l'affichage du menu popup dans une cellule.
 */
private void showpopupMenu() {
    if (!isShowing() && this != null) {
        this.show();
    }
}


/**
 * Ajoute un item à la liste
 * 
 * @param stg String nom de l'item
 * @param width double taille préférée
 */
public void addItem(String stg, double width) {
    if (stg != null) {
        items.add(new BoxItem(stg, items, width));
    }
}


/**
 * Retourne la description du contenu de la liste
 */
public String toString() {
    final StringBuilder stgBuilder = new StringBuilder("[ ");
    if (items != null && items.size() > 0) {
        final BoxItem lastItem = items.get(items.size() - 1);
        for (BoxItem item : items) {
            if (item != null) {
                stgBuilder.append(item.getName());
                if (!item.equals(lastItem)) {
                    stgBuilder.append(", ");
                }
            }
        }
    }
    stgBuilder.append(" ]");
    return stgBuilder.toString();

}

public class BoxItem extends HBox {

private Label lbl = null;
private Button btn = null;
private ObservableList<BoxItem> listItems;


/**
 * Constructeur.
 * 
 * @param stg String nom de la box
 * @param items ObservableList<BoxItem> liste d'items de la combobox
 * @param prefWidth int largeur de la combobox
 */
public BoxItem(String stg, final ObservableList<BoxItem> items, double prefWidth) {
    super();
    this.listItems = items;
    if (stg != null) {
        this.setSpacing(40);
        lbl = new Label(stg);
        lbl.setPrefWidth(prefWidth);
        btn = new Button("x");
        this.getChildren().addAll(lbl, btn);

        btn.setOnMousePressed(new EventHandler<Event>() {
            @Override
            public void handle(Event arg0) {
                final BoxItem bx = (BoxItem) btn.getParent();
                if (bx != null) {
                    listItems.remove(bx);
                }
             }
  });
     }
 }


 /**
 * Retourne le texte inscrit dans le label
 * 
 * @return String
 */
public String getName() {
    if (lbl != null) {
        return lbl.getText();
    }
    return null;
}


/**
 * retourne le bouton contenu dans une box
 * 
 * @return Button
 */
public Button getBtn() {
    return btn;
}
}
}
公共类cbbxeditsupper扩展组合框{
私有文本字段编辑器=null;
私有可观察列表项=空;
专用双预宽=0.0;
/**
*建筑工人。
* 
*@param addedItems observeList
*@param prefWidth双倍大的préférée
*/
公共CBBXeditSupper(可观察列表加法器,最终双前缀宽度){
//属性初始化
editor=this.getEditor();
items=this.getItems();
this.prefWidth=prefWidth;
此.setPrefWidth(prefWidth);
//单元内容的初始化
this.setCellFactory(新回调(){
@凌驾
公共ListCell调用(ListView p){
最终ListCell单元格=新ListCell(){
@凌驾
受保护的void updateItem(BoxItem t,布尔bln){
超级更新项(t,bln);
如果(t!=null){
设定图形(t);
}否则{
设置图形(空);
}
}
};
返回单元;
}
});
//déininition du转换器
this.setConverter(新的StringConverter(){
@凌驾
公共字符串到字符串(BoxItem cbbx){
如果(cbbx==null){
返回null;
}否则{
返回cbbx.getName();
}
}
@凌驾
public BoxItem fromString(字符串id){
如果(id!=null){
最终BoxItem框=新的BoxItem(id、项目、宽度);
返回框;
}否则{
返回null;
}
}
});
/*一份物品清单*/
if(addedItems!=null&&addedItems.size()>0){
for(字符串stg:addedItems){
如果(stg!=null){
final BoxItem hbox=新的BoxItem(stg,items,this.prefWidth);
添加项目(hbox);
}
}
}
//你可以进来,也可以出去
this.addEventFilter(按KeyEvent.KEY_,新建EventHandler()){
公共无效句柄(最终KeyEvent事件){
if(event!=null&&event.getCode().equals(KeyCode.ENTER)){
if(editor.getText().trim().length()>0){
addItem(editor.getText(),prefWidth);
编辑器.clear();
}
}
}
});
//propriétés premier元素的可编辑et选择
此.setEditable(true);
这个.getSelectionModel().selectFirst();
//菜单弹出窗口中的文字字段和文本框的编辑
editor.focusedProperty().addListener(新的ChangeListener()){
@凌驾

public void已更改(observeValue我认为出现问题的原因是
BoxItem
是一个
节点
子类,即您混合了视图类型和数据类型。(在
updateItem()方法中有
BoxItem t;
setGraphic(t);
)这对于组合框来说尤其糟糕,因为所选项目最终尝试在场景图中出现两次(一次出现在组合框的下拉列表中,一次出现在显示所选内容的“按钮单元格”中)

请参阅中的“关于将节点插入组合框项目列表的警告”

相反,请使用不同的类来表示正在显示的数据,并使用UI控件来显示这些数据

 Callback<TableColumn<DonorData, ObservableList<BoxItem>>, TableCell<DonorData,   ObservableList<BoxItem>>> cellFactoryEditingCell = new Callback<TableColumn<DonorData, ObservableList<BoxItem>>, TableCell<DonorData, ObservableList<BoxItem>>>() {
        public TableCell<DonorData, ObservableList<BoxItem>> call(TableColumn<DonorData, ObservableList<BoxItem>> data) {
            return new CbbxEditingCell<DonorData, ObservableList<BoxItem>>();
        }
    };

    colDonorOtherRef.setCellValueFactory(new PropertyValueFactory<DonorData, ObservableList<BoxItem>>("othersRef"));
    colDonorOtherRef.setCellFactory(cellFactoryEditingCell);
    colDonorOtherRef.setOnEditCommit(new EventHandler<CellEditEvent<DonorData, ObservableList<BoxItem>>>() {
        @Override
        public void handle(CellEditEvent<DonorData, ObservableList<BoxItem>> event) {
            final DonorData rec = event.getTableView().getItems().get(event.getTablePosition().getRow());
            //TODO action
}
    });
public class CbbxEditingCell<S, T> extends TableCell<S, T> {
private CbbxEditSuppr cbbx;
private ObservableList<String> listValues = null;

private boolean isSelectFirst = false;


public CbbxEditingCell() {
    listValues = FXCollections.observableArrayList(new ArrayList());
}


@Override
public void startEdit() {
    if (!isEmpty()) {
        super.startEdit();
        createTextField();
        setText(null);
        setGraphic(cbbx);
    }
}


@Override
public void cancelEdit() {
    super.cancelEdit();
    try {
        if (!getItem().toString().equals("null")) {
            setText(cbbx.toString());
        }
    } catch (Exception e) {
    }
    setGraphic(null);
}


@Override
public void updateItem(T item, boolean empty) {
    super.updateItem(item, empty);
    if (empty) {
        setText(null);
        setGraphic(null);
    } else {
        if (isEditing()) {
            setText(null);
            setGraphic(cbbx);
        } else {
            if (getItem() != null && cbbx != null) {
                setText(cbbx.toString());
            } else {
                setText(null);
            }
            setGraphic(null);
        }
    }
}


private void createTextField() {
    final double width = this.getWidth() - this.getGraphicTextGap() * 2;
    cbbx = new CbbxEditSuppr((ObservableList<String>) listValues, width);
    if (isSelectFirst) {
        cbbx.getSelectionModel().selectFirst();
    }
    cbbx.setMinWidth(width);
    cbbx.setOnKeyReleased(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent t) {
            if (t.getCode() == KeyCode.ENTER) {
                commitEdit((T) cbbx.getItems());
            } else if (t.getCode() == KeyCode.ESCAPE) {
                cancelEdit();
            }
        }
    });
    cbbx.focusedProperty().addListener(new ChangeListener<Boolean>() {
        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            if (!newValue) {
                commitEdit((T) cbbx.getItems());
            }

        }
    });

}


public void selectFirstItem() {
    isSelectFirst = true;
}

}