Элементы JavaFX ListView стекаются снизу

#listview #javafx-8

#listview #javafx-8

Вопрос:

Я новичок в JavaFX и пытался внедрить систему чата. Моя проблема в том, что я хочу создать перевернутый список, который будет обновлять свои элементы снизу. В Android это может быть достигнуто путем включения «стека снизу», как в этом сообщении. Как это может быть достигнуто в JavaFX.

Ответ №1:

Просто продолжайте добавлять новые элементы с 0-м индексом в список элементов вашего ListView.

 listView.getItems().add(0, newItem);
  

Пример приложения

перевернуто

 import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.stage.Stage;

public class ListViewViewer extends Application {
    @Override
    public void start(Stage stage) {
        ListView<String> list = new ListView<>();
        ObservableList<String> items = list.getItems();
        items.add(0, "1");
        items.add(0, "2");
        items.add(0, "3");
        items.add(0, "4");

        stage.setScene(new Scene(list));
        stage.show();
    }

   public static void main(String[] args) {
        launch(args);
    }
}
  

Если то, что вы хотели, было 1,2,3,4, а не 4,3,2,1, как в примере, тогда просто добавьте новые элементы в список элементов без указания индекса вставки:

 listView.getItems().add(newItem);
  

Список элементов является наблюдаемым списком, поэтому, если вы измените порядок элементов в наблюдаемом списке (например, отсортируете его или перетасуете), обновленный порядок элементов будет немедленно отражен в ListView.


Обновленный ответ на основе обновленного вопроса

В статье, на которую вы ссылаетесь, упоминается функциональность Android для добавления элементов в самую нижнюю видимую ячейку в списке (ваша функциональность «стекать снизу»), такой не существует в основных библиотеках JavaFX 8. Вы могли бы подать запрос на функцию для такой функциональности, если хотите.

Вероятно, лучшим способом реализации такой функциональности было бы использование пользовательского скина для ListView. Однако это было бы довольно сложной задачей.

Вы можете имитировать функциональность «стека с кнопки», предварительно заполнив ListView пустыми элементами, чтобы новые элементы добавлялись в нижнюю часть списка (удаляя фиктивные пустые элементы по мере добавления новых элементов). Вот пример такого подхода:

stackedfrombottom

 import javafx.animation.*;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
import javafx.util.Duration;

public class ListViewViewer extends Application {
    private static final int MAX_MESSAGES = 20;
    private static final int DISPLAYED_MESSAGES = 8;
    private static final int CELL_HEIGHT = 24;

    private int msgNum = 0;

    @Override
    public void start(Stage stage) {
        ListView<String> list = new ListView<>();
        ObservableList<String> items = list.getItems();
        for (int i = 0; i < DISPLAYED_MESSAGES; i  )  {
            items.add("");
        }
        list.setMinHeight(ListView.USE_PREF_SIZE);
        list.setPrefHeight(DISPLAYED_MESSAGES * CELL_HEIGHT   2);
        list.setMaxHeight(ListView.USE_PREF_SIZE);

        stage.setScene(new Scene(list));
        stage.setResizable(false);
        stage.show();

        simulateMessaging(list);
    }

    private void addMessage(ObservableList<String> items, String message) {
        if (items.get(0).equals("") || items.size() >= MAX_MESSAGES) {
            items.remove(0);
        }

        items.add(message);
    }

    private void simulateMessaging(ListView<String> list) {
        Timeline messageMaker = new Timeline(
                new KeyFrame(
                        Duration.seconds(1),
                        event -> {
                            addMessage(list.getItems(), nextMessage());
                            if (list.getItems().size() > DISPLAYED_MESSAGES) {
                                list.scrollTo(list.getItems().size() - 1);
                            }
                        }
                )
        );

        messageMaker.setCycleCount(Timeline.INDEFINITE);

        PauseTransition pause = new PauseTransition(Duration.seconds(2));
        pause.setOnFinished(event -> messageMaker.play());
        pause.play();
    }

    private String nextMessage() {
        return "msg "   msgNum  ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}
  

Настройте образец так, как вам нужно, чтобы получить именно ту функциональность, которая вам требуется.

Комментарии:

1. Я попробовал ваш метод, но элементы все еще находятся в верхней части listview. Как я могу изменить выравнивание элементов по низу, как в обычных программах чата?

2. Я отредактировал вопрос, чтобы сделать мой вопрос более понятным. Пожалуйста, обратитесь.

Ответ №2:

Flowless, который является альтернативой ListView , позволяет вам складывать элементы снизу. Вам просто нужно установить gravity на REAR при создании экземпляра:

 VirtualFlow<String, ?> flow = VirtualFlow.createVertical(
        items, cellFactory, VirtualFlow.Gravity.REAR) 
  

Ответ №3:

Всем, кто может счесть это своей проблемой, используйте

 Collections.reverse(arrayList);
  

Это просто, и его просто нужно применить в самом конце, чтобы полностью изменить ваш массив.

Ответ №4:

Альтернативное решение.

     list.setRotate(180);
    list.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
    entry.setRotate(180);
    entry.setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT);
  

и, наконец, переверните прокрутку списка.