Как сохранить последнюю выбранную ячейку в ListView выбранной после нажатия кнопки в JavaFX? - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть JavaFX, который отображает 2 отдельных ListView, например, так:

enter image description here

Есть 2 кнопки для перемещения выбранной ячейки в правый список.Прямо сейчас, если я выберу ячейку, скажем «Amazon Web Services» справа, а затем нажму кнопку «<< Сохранить список», она переместится влево. </p>

Однако, если я хочуТеперь переместите 2-й предмет, который называется «Рита М. Пауэлл», также в список ведения. Я должен выбрать эту ячейку и снова нажать кнопку «Сохранить список».

То, что я хотел бы сделать, это оставить верхнюю строку этого ListView выбранной даже после нажатия кнопок, чтобы мне не приходилось возвращаться и снова выбирать верхнюю ячейку.

На данный момент, как я это делаю, в моем контроллере хранится переменная экземпляра private ListServer selected; и присваивается эта переменная всякий раз, когда я нажимаю на ячейку:

deleteListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            selected = newValue;
        });

        keepListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            selected = newValue;
        });

Затем две кнопки обрабатывают перемещениеэти ячейки путем изменения свойств, прикрепленных к ним:

    @FXML
    public void moveKeep() {
        if (selected != null) {
            selected.setKeep(true);
            wrapKeepList();
        }
    }

    @FXML
    public void moveDelete() {
        if (selected != null) {
            selected.setKeep(false);
            wrapDeleteList();
        }
    }

Остальная часть кода контроллера:

public class ListServerOverviewController {


    @FXML
    private JFXListView<ListServer> deleteListView;

    @FXML 
    private JFXListView<ListServer> keepListView;

    @FXML
    private JFXButton scanButton;

    @FXML
    private JFXButton pauseButton;

    @FXML
    private JFXButton moveDeleteButton;

    @FXML
    private JFXButton moveKeepbutton;

    private BooleanProperty isScanning = new SimpleBooleanProperty(false);

    private MainApp mainApp;

    private FilteredList<ListServer> keepList;

    private FilteredList<ListServer> deleteList;

    private AtomicBoolean paused = new AtomicBoolean(false);

    private Thread thread;

    private ListServer selected;


    public ListServerOverviewController() {

    }

    @FXML
    public void initialize() {
        scanButton.setContentDisplay(ContentDisplay.RIGHT);
    }

    public void setMainApp(MainApp mainApp) {
        this.mainApp = mainApp;

        wrapDeleteList();
        wrapKeepList();

        scanButton.visibleProperty().bind(isScanning.not());
        pauseButton.visibleProperty().bind(isScanning);

        deleteListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            selected = newValue;
        });

        keepListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            selected = newValue;
        });
    }

    private void wrapKeepList() {
        keepList = new FilteredList<>(mainApp.getListServerList(), p -> p.getKeep());

        if (!keepList.isEmpty()) {
            keepListView.setItems(keepList);
            keepListView.setCellFactory(param -> new ListCell<ListServer>() {
                @Override
                protected void updateItem(ListServer item, boolean empty) {
                    super.updateItem(item,  empty);

                    if (empty || item == null) {
                        setText(null);
                    } else {
                        setText(item.getName());
                    }
                }
            });
        }
    }

    private void wrapDeleteList() {
        deleteList = new FilteredList<>(mainApp.getListServerList(), p -> !p.getKeep());

        if (!deleteList.isEmpty()) {
            deleteListView.setItems(deleteList);

            deleteListView.setCellFactory(param -> new ListCell<ListServer>() {
                @Override
                protected void updateItem(ListServer item, boolean empty) {
                    super.updateItem(item,  empty);

                    if (empty || item == null) {
                        setText(null);
                    } else {
                        setText(item.getName());
                    }
                }
            });
        }
    }

    @FXML
    public void moveKeep() {
        if (selected != null) {
            selected.setKeep(true);
            wrapKeepList();
        }
    }

    @FXML
    public void moveDelete() {
        if (selected != null) {
            selected.setKeep(false);
            wrapDeleteList();
        }
    }

    @FXML
    public void handleScanInbox() {
        isScanning.set(true);

        if (thread == null) {
            thread = new Thread() {
                public void run() {
                    mainApp.handleScanInbox(paused);
                }
            };
            thread.setDaemon(true);
            thread.start();
        } else {
            synchronized (paused) {
                if (paused.get()) {
                    paused.set(false);
                    paused.notify();
                }
            }
        }

    }

    @FXML
    public void handlePauseScanInbox() {
        paused.compareAndSet(false,  true);
        isScanning.set(false);

    }

}

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Использование слушателя для помещения выбранного значения в поле не очень хорошая идея.Оба слушателя используют одно и то же поле, поэтому последнее изменение выбора определяет элемент для перемещения, а не последнее изменение для ListView.Кроме того, стоимость извлечения значения минимальна и может быть легко выполнена в обработчике событий с использованием значения.

Кроме того, не нужно обновлять списки при каждом изменении свойства keep.Используйте модель выбора, чтобы выбрать перенесенный элемент после перемещения его между списками:

public static class Item {
    private final String text;
    private final BooleanProperty keep = new SimpleBooleanProperty();

    public Item(String text) {
        this.text = text;
    }

    @Override
    public String toString() {
        return text;
    }

    public BooleanProperty keepProperty() {
        return keep;
    }

    public boolean isKeep() {
        return keep.get();
    }

    public void setKeep(boolean value) {
        keep.set(value);
    }

}

private static void move(ListView<Item> source, ListView<Item> target) {
    Item item = source.getSelectionModel().getSelectedItem();
    if (item != null) {
        item.setKeep(!item.isKeep());
        target.getSelectionModel().clearSelection();
        target.getSelectionModel().select(item);
    }
}

@Override
public void start(Stage primaryStage) {
    ObservableList<Item> data = FXCollections.observableArrayList(new Callback<Item, Observable[]>() {

        @Override
        public Observable[] call(Item param) {
            return new Observable[] { param.keepProperty() };
        }

    });

    FilteredList<Item> keep = data.filtered(item -> item.isKeep());
    FilteredList<Item> remove = data.filtered(item -> !item.isKeep());

    ListView<Item> leftList = new ListView<>(keep);
    ListView<Item> rightList = new ListView<>(remove);

    Button moveLeft = new Button("<<");
    moveLeft.setOnAction(evt -> move(rightList, leftList));

    Button moveRight = new Button(">>");
    moveRight.setOnAction(evt -> move(leftList, rightList));

    for (int i = 0; i < 40; i++) {
        data.add(new Item(Integer.toString(i)));
    }

    Scene scene = new Scene(new HBox(10, leftList, moveLeft, moveRight, rightList));
    primaryStage.setScene(scene);
    primaryStage.show();
}

Если могут быть разные элементы Item, которые могут дать true при сравнении с использованием equals, вам следует использоватьМетоды TransformationList, чтобы найти индекс для выбора и сделать выбор по индексу:

private static void move(ListView<Item> source, ListView<Item> target) {
    FilteredList<Item> sourceList = (FilteredList<Item>) source.getItems();
    FilteredList<Item> targetList = (FilteredList<Item>) target.getItems();
    Item item = source.getSelectionModel().getSelectedItem();
    if (item != null) {
        int index = sourceList.getSourceIndex(source.getSelectionModel().getSelectedIndex());
        item.setKeep(!item.isKeep());
        index = targetList.getViewIndex(index);
        target.getSelectionModel().clearAndSelect(index);
    }
}
0 голосов
/ 12 декабря 2018

Я бы рекомендовал вместо того, чтобы хранить ссылку на выбранный элемент для «выбранной» переменной экземпляра, получить выбранный элемент на лету, когда вы нажимаете кнопку.Также после выполнения требуемой операции вы вызываете метод selectFirst () объекта selectionModel, чтобы выбрать первый вариант.Нечто подобное ..

// I assume moving from delete to keep
@FXML
public void moveKeep() {
    if (deleteListView.getSelectionModel().getSelectedItem()!= null) {
        deleteListView.getSelectionModel().getSelectedItem().setKeep(true);
        wrapKeepList();
        wrapDeleteList();
        deleteListView.getSelectionModel().selectFirst();
    }
}

Также вам не нужно сохранять реализацию фабрики ячеек в методах wrapXXX.вы можете переместить заводскую настройку ячейки в метод setMainApp ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...