我遇到了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;
}
}
}
然后我用这个callbak启动我的colum:
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
}
});
with:CbbxEditingCell.java
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;
}
}
我的问题:当我点击一个单元格时,我总是一个空的组合框。我不知道如何修改我的回调以获得该单元格中的行或数据的引用。
你有什么想法吗? 感谢
答案 0 :(得分:0)
我认为问题出现是因为BoxItem
是Node
子类 - 即您正在混合视图类型和数据类型。 (BoxItem t;
方法中有setGraphic(t);
和updateItem()
。)ComboBox
特别糟糕,因为所选项最终会尝试在场景图中出现两次(一次在ComboBox
下拉,一次在&#34;按钮单元格&#34;显示所选内容。
参见&#34;关于将节点插入ComboBox项目列表的警告&#34;在ComboBox
Javadocs。
相反,使用不同的类来表示您正在显示的数据以及用于显示它们的UI控件。