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();
    }

может содержать некоторые ошибки, но это работает в моей ситуации

Другие вопросы по тегам