【问题标题】:Javafx ListView update dynamicallyJavafx ListView 动态更新
【发布时间】:2018-08-09 10:51:16
【问题描述】:

我正在使用 JavaFx 创建一个聊天应用程序。我的朋友列表被加载到 ListView 中。我的要求是在用户收到朋友的消息时显示通知图标。为此,我需要知道朋友所在的单元格,还需要显示通知图标。我无法找到一种方法来做到这一点,因为我对 FX 很陌生。 任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 使用单元格渲染。您可以将场景(FXML)显示为列表单元格值。
  • 嗨,谢谢。你能给我举一个很好的例子吗?我有点迷路了
  • 当然......

标签: java javafx fxml


【解决方案1】:

将您收到通知的朋友的信息存储在一些 observable 中。这可能是项目类本身

public class Friend {

    private final IntegerProperty messageCount = new SimpleIntegerProperty();

    public int getMessageCount() {
        return messageCount.get();
    }

    public void setMessageCount(int value) {
        messageCount.set(value);
    }

    public IntegerProperty messageCountProperty() {
        return messageCount;
    }

    ...

}

或像ObservableMap这样的外部数据结构,如以下示例中使用的:

public class Friend {

    private final String name;

    public String getName() {
        return name;
    }

    public Friend(String name) {
        this.name = name;
    }

}
@Override
public void start(Stage primaryStage) {
    // map storing the message counts by friend
    final ObservableMap<Friend, Integer> messageCount = FXCollections.observableHashMap();

    ListView<Friend> friendsListView = new ListView<>();
    friendsListView.setCellFactory(lv -> new ListCell<Friend>() {
        final StackPane messageNotification;
        final Text numberText;
        final InvalidationListener listener;

        {
            // notification item (white number on red circle)
            Circle background = new Circle(10, Color.RED);

            numberText = new Text();
            numberText.setFill(Color.WHITE);

            messageNotification = new StackPane(background, numberText);
            messageNotification.setVisible(false);

            listener = o -> updateMessageCount();
            setGraphic(messageNotification);
        }

        void updateMessageCount() {
            updateMessageCount(messageCount.getOrDefault(getItem(), 0));
        }

        void updateMessageCount(int count) {
            boolean messagesPresent = count > 0;
            if (messagesPresent) {
                numberText.setText(Integer.toString(count));
            }
            messageNotification.setVisible(messagesPresent);

        }

        @Override
        protected void updateItem(Friend item, boolean empty) {
            boolean wasEmpty = isEmpty();
            super.updateItem(item, empty);
            if (wasEmpty != empty) {
                if (empty) {
                    messageCount.removeListener(listener);
                } else {
                    messageCount.addListener(listener);
                }
            }

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

        }

    });

    Random random = new Random();
    List<Friend> friends = Stream
            .of(
                    "Sheldon",
                    "Amy",
                    "Howard",
                    "Bernadette",
                    "Lennard",
                    "Penny")
            .map(Friend::new)
            .collect(Collectors.toCollection(ArrayList::new));

    friendsListView.getItems().addAll(friends);

    List<Friend> messages = new ArrayList(friends.size() * 2);

    // 2 messages for each friend in random order
    Collections.shuffle(friends, random);
    messages.addAll(friends);
    Collections.shuffle(friends, random);
    messages.addAll(friends);

    // demonstrate adding/removing messages via timelines
    Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {

        Iterator<Friend> iterator = messages.iterator();

        @Override
        public void handle(ActionEvent event) {
            messageCount.merge(iterator.next(), 1, Integer::sum);
        }

    }));
    timeline.setCycleCount(messages.size());

    Timeline removeTimeline = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {

        Iterator<Friend> iterator = messages.iterator();

        @Override
        public void handle(ActionEvent event) {
            messageCount.merge(iterator.next(), 1, (a, b) -> a - b);
        }

    }));
    removeTimeline.setCycleCount(messages.size());

    new SequentialTransition(timeline, removeTimeline).play();

    Scene scene = new Scene(friendsListView);

    primaryStage.setScene(scene);
    primaryStage.show();
}

对于存储在Friend 类中的消息计数,您需要修改注册侦听器并稍微更新单元格。

listener = o -> updateMessageCount(getItem().getMessageCount());
@Override
protected void updateItem(Friend item, boolean empty) {
    Friend oldItem = getItem();
    if (oldItem != null) {
        oldItem.messageCountProperty().removeListener(listener);
    }

    super.updateItem(item, empty);

    if (empty || item == null) {
        setText("");
        updateMessageCount(0);
    } else {
        setText(item.getName());
        item.messageCountProperty().addListener(listener);
        updateMessageCount(item.getMessageCount());
    }

}

【讨论】:

  • 嗨,谢谢。我试过这样做,但由于我已经为朋友的显示图片设置了图形集,所以我对此感到困惑。如何处理这两个图形?我用图片编辑了我的问题
  • 你好,你能解释一下 boolean wasEmpty = isEmpty(); super.updateItem(项目,空); if (wasEmpty != empty) { if (empty) { messageCount.removeListener(listener); } else { messageCount.addListener(listener); } }
  • 如果单元格从空变为非空或反之,则根据更新后空属性的状态添加或删除侦听器。 (您不需要更新空单元格,因为无论地图的状态如何,它们始终保持为空)
猜你喜欢
  • 2017-04-21
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
  • 1970-01-01
  • 2016-06-07
  • 1970-01-01
  • 1970-01-01
  • 2012-06-18
相关资源
最近更新 更多