Javafx, как получить ячейку из списка (не значение)
Я хочу получить ячейку (узел, а не данные) из списка по индексу. Мне нужно привести ее к моей пользовательской ячейке и вызвать ее функцию.
Я нашел много вопросов, спрашиваю, как получить значение, но я не нахожу ничего о том, как получить саму ячейку. Я пытаюсь использовать listView.getChildrenUnmodifiable().get(index)
, но это не работа.
Функция, которую я хочу достичь, это щелкнуть правой кнопкой мыши по ячейке списка, затем открыть контекстное меню, в котором есть команда "переименовать", когда я щелкаю по общему списку, startEdit
Функция ячейки должна быть вызвана.
Как я могу это сделать?
2 ответа
Вы должны установить контекстное меню на отдельные ячейки, а не на само представление списка. Вот быстрый пример:
Класс контроллера с представлением списка и методами для вызова из пунктов контекстного меню:
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
public class Controller {
@FXML
private ListView<String> listView ;
public void initialize() {
for (int i = 1 ; i <= 20 ; i++) {
listView.getItems().add("Item "+i);
}
listView.setCellFactory(lv -> new ListCellWithContextMenu(this));
}
public void edit(int index) {
listView.edit(index);
}
public void delete(int index) {
listView.getItems().remove(index);
}
}
Ячейка реализации:
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.cell.TextFieldListCell;
public class ListCellWithContextMenu extends TextFieldListCell<String> {
private final ContextMenu contextMenu ;
public ListCellWithContextMenu(Controller controller) {
contextMenu = new ContextMenu();
MenuItem delete = new MenuItem("Delete");
MenuItem edit = new MenuItem("Edit");
contextMenu.getItems().addAll(edit, delete);
edit.setOnAction(e -> controller.edit(getIndex()));
delete.setOnAction(e -> controller.delete(getIndex()));
setConverter(TextFormatter.IDENTITY_STRING_CONVERTER);
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setContextMenu(null);
} else {
setContextMenu(contextMenu);
}
}
}
Для полноты, файл FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.ListView?>
<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller">
<left>
<ListView fx:id="listView" editable="true" />
</left>
</BorderPane>
и класс приложения:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ListViewWithContextMenu extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Scene scene = new Scene(FXMLLoader.load(getClass().getResource("ListViewWithContextMenu.fxml")));
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
James_D прав, вы можете зарегистрировать контекстные меню для отдельных ячеек. Но в ситуации, когда у меня много кода относительно контекстного меню, переписать все может вызвать другие проблемы. После некоторой попытки я использую другой способ.
Для простоты я пишу два многократно используемых класса для реализации функции, которая получает ячейку по индексу из списка напрямую.
Если вы считаете полезным, вы можете использовать код ниже.
//let your cell extend this class
public class GetAbleListCell<T> extends ListCell<T>{
private ListViewHelper<T> libraryListHelper;
public GetAbleListCell(ListViewHelper<T> libraryListHelper) {
this.libraryListHelper = libraryListHelper;
}
@Override
public void updateIndex(int i) {
// TODO Auto-generated method stub
super.updateIndex(i);
if(getIndex()>0)
{
libraryListHelper.setCell(getIndex(),this);
}
}
}
//helper class
public class ListViewHelper<T> {
private ObservableList<GetAbleListCell<T>> list=FXCollections.observableArrayList();
public GetAbleListCell<T> getCell(int index) {
return list.get(index);
}
public void setCell(int index, GetAbleListCell<T> getAbleListCell) {
while(list.size()<index+1)
{
list.add(null);
}
list.set(index, getAbleListCell);
}
}
пример
this.libraryListHelper=new ListViewHelper();
libraryLV.setCellFactory(param -> new LibraryCell(libraryListHelper));
.........
private void renameCurrentSelectedItems() {
//get cell directly
LibraryCell cell=(LibraryCell) libraryListHelper.getCell(libraryLV.getSelectionModel().getSelectedIndex());
cell.startEdit();
}
может содержать некоторые ошибки, но это работает в моей ситуации