Кнопка привязки JavaFX Listview к индексу ячейки
Я пытаюсь создать собственное представление с помощью JavaFX, которое позволяет 2 кнопкам "Изменить пользователя" и "Просмотреть пользователя" поместить в ячейку.
У меня есть встроенный адаптер, но у меня возникают проблемы с назначением индекса кнопке при создании ячейки, это проблема, поскольку, когда я нажимаю кнопку внутри ячейки, я получаю исключение нулевого указателя.
РЕДАКТИРОВАТЬ 04/04/2014: я немного обновил логику своей программы, но я все еще изо всех сил пытаюсь найти решение моей проблемы - назначенный индекс иногда корректен, но в основном неверен (я настроил журнал, чтобы дать мне текущий индекс, и он резко колеблется, что приводит меня к выводу, что мой конструктор ячейки ненадежен)
Теперь я использую следующий код: populateListView():
public void populateListView() {
// Zero the index each time the list view is repopulated to
// bind to the correct button
index = 0;
// Refresh the lists contents to null
lstNotes.setItems(null);
// Observable list containing items to add
ObservableList notes = populateObservable(thisTenant.getNotes());
// Set the items returned by populateObservable(T);
lstNotes.setItems(notes);
lstNotes.setFixedCellSize(50);
// Use a cell factory for custom styling
lstNotes.setCellFactory(new Callback<ListView, ListCell>() {
@Override
public ListCell call(ListView listView) {
NoteCell nCell = new NoteCell(index, controller);
index++;
nCell.getStyleClass().add("border-bottom");
return nCell;
}
});
}
Здесь комментарии довольно понятны - наблюдаемый список элементов заполняется с помощью этого метода - populateObservable(NoteList n):
public ObservableList populateObservable(ArrayList<Note> notesArray) {
ObservableList notes = FXCollections.observableArrayList();
// Loop through the users Notes array and create a listview item
for(int i = 0; i < notesArray.size(); i++) {
Note thisNote = notesArray.get(i);
notes.add(thisNote.getMessage());
}
return notes;
}
Наконец, в моей фабрике ячеек создается собственное представление (стиль не имеет отношения к вопросу), следует отметить, что ему передается ссылка на мой контроллер, чтобы я мог получить доступ к методам - в классе NoteCell у меня есть метод для удаления строка с заданным индексом (это то, что дает искаженные результаты)
cross.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
ScreensFramework.logGeneral.writeToFile("I am removing from index " + String.valueOf(thisIndex));
if(thisTenant.removeNoteAt(thisIndex, true)){
controller.populateListView();
} else {
controller.populateListView();
}
}
});
вызов функции populateListView () просто обновляет содержимое списка и перестраивает его в зависимости от обновленного массива Note арендатора.
Метод RemoveNoteAt() отправляет запрос на удаление в мою базу данных и удаляет примечание из массива примечаний арендаторов по указанному индексу (но я не всегда получаю правильный индекс, как указано выше, так как не могу найти эффективный способ привязки кнопка в эту ячейку ListViews и моя слабая попытка передать индекс не работают).
Я надеюсь, что это обновление предоставит более четкую область для моего вопроса, пожалуйста, запросите, если вам нужна дополнительная информация, чтобы получить более четкое понимание этого.
РЕДАКТИРОВАТЬ: NoteCell код:
public class NoteCell extends ListCell<String> {
HBox hbox = new HBox();
HBox c = new HBox();
Pane b = new HBox();
Pane pane = new Pane();
Label msg = new Label();
Label date = new Label();
Button cross = new Button();
Tenant thisTenant;
int thisIndex;
String lastItem;
public NoteCell(int index, UserInfoController controller) {
super();
try{
thisTenant = controller.getTenant();
Note currNote = thisTenant.getNoteAt(index);
date = new Label(currNote.getDate());
System.out.println(thisTenant.getNotes());
thisIndex = index;
date.setStyle("-fx-text-fill: #fff !important; -fx-font-family: Helvetica; -fx-font-weight: bold; -fx-font-size: 12px; -fx-background-color: #f9246b; -fx-border-color: #FE246C; -fx-padding: 8 8 6 8; -fx-border-radius: 6; -fx-background-radius: 6");
b.setStyle("-fx-padding: 10px 5px 10px 5px");
msg.setStyle("-fx-text-fill: #fafafa; -fx-font-size: 14px; -fx-font-family: 'Open Sans Light'; -fx-label-padding: 10px");
cross.getStyleClass().add("button_close");
cross.setTranslateY(20);
msg.setAlignment(Pos.CENTER_LEFT);
pane.setTranslateY(20);
b.getChildren().add(date);
c.getChildren().add(cross);
hbox.getChildren().addAll(b, msg, pane, cross);
HBox.setHgrow(pane, Priority.ALWAYS);
// Deletes the note
cross.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
ScreensFramework.logGeneral.writeToFile("I am removing from index " + String.valueOf(thisIndex));
if(thisTenant.removeNoteAt(thisIndex, true)){
controller.populateListView();
} else {
controller.populateListView();
}
}
});
} catch (Exception e) {
ScreensFramework.logError.writeToFile(e.getMessage());
}
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(null); // No text in label of super class
if (empty) {
lastItem = null;
setGraphic(null);
} else {
lastItem = item;
msg.setText(item!=null ? item : "<null>");
setGraphic(hbox);
}
}
}
РЕДАКТИРОВАТЬ: Есть ли способ при создании ячеек ListView я мог бы передать текущий индекс этой ячейки в "CellFactory"?
С уважением, Алекс
1 ответ
Каждая клетка знает свой индекс:
public class Demo extends Application {
ListView<String> list = new ListView<String>();
ObservableList<String> data = FXCollections.observableArrayList(
"chocolate", "salmon", "gold", "coral", "darkorchid",
"darkgoldenrod", "lightsalmon", "black", "rosybrown", "blue",
"blueviolet", "brown");
@Override
public void start(Stage stage) {
VBox box = new VBox();
Scene scene = new Scene(box, 200, 200);
stage.setScene(scene);
box.getChildren().addAll(list);
VBox.setVgrow(list, Priority.ALWAYS);
list.setItems(data);
list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> list) {
return new ButtonCell();
}
});
stage.show();
}
static class ButtonCell extends ListCell<String> {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
final Button btn = new Button(item + " with index " + getIndex());
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("I am a " + getItem() + " with index " + getIndex());
}
});
setGraphic(btn);
} else {
setGraphic(null);
}
}
}
public static void main(String[] args) {
launch(args);
}
}