【问题标题】:Why ListView Multiple Selection Model Updates Automatically为什么 ListView 多选模型会自动更新
【发布时间】:2016-10-28 06:33:58
【问题描述】:

我正在学习JavaFX ListView 我想知道为什么当我选择listViewLeft 的项目时listViewRight 的项目会自动更新?

FXML 代码:

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.ListView ?>
<?import javafx.scene.control.Label ?>
<?import javafx.scene.control.SelectionMode ?>
<?import javafx.scene.control.MultipleSelectionModel ?>
<?import javafx.scene.control.CheckBox ?>
<?import javafx.collections.FXCollections ?>
<?import java.lang.String ?>
<BorderPane prefWidth="600" prefHeight="250" xmlns:fx="http://javafx.com/fxml" fx:controller="ListViewController">
    <left>
        <ListView fx:id="listViewLeft" editable="true">
            <items>
                <FXCollections fx:id="collection" fx:factory="observableArrayList">
                    <String fx:value="Good" />
                    <String fx:value="Bad" />
                    <String fx:value="Average" />
                </FXCollections>
            </items>
        </ListView>
    </left>

    <right>
        <ListView fx:id="listViewRight" />
    </right>
</BorderPane>

控制器代码:

import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.scene.control.CheckBox;
import javafx.scene.control.SelectionMode;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.ChangeListener;

public class ListViewController{
    @FXML private ListView<String> listViewLeft;
    @FXML private ObservableList<String> collections;
    @FXML private CheckBox newItem;
    @FXML private ListView<String> listViewRight;

    public void initialize(){
        collections = listViewLeft.getItems();
        listViewLeft.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);


        listViewRight.setItems(listViewLeft.getSelectionModel().getSelectedItems());
    }
}

当我从listViewLeft 中选择项目时,该项目会自动显示在listViewRight 中,为什么?我刚刚打电话给listViewLeft.getSelectionModel().getSelectedItems() 将所有选定的项目添加到listViewRight 为什么它binds 到listViewRight ?

【问题讨论】:

  • 您想动态更改 listViewRight 项还是最初想将这些项设置为所有,在初始化期间,从 listViewLeft 中选择项b>?

标签: listview javafx


【解决方案1】:

“后备名单”

ListView 引用了ObservableList,您可以通过getItems() 访问它; ObservableList 包含在列表视图中显示的元素。 ObservableList 有时被称为ListView 的“后备名单”(我将在此说明)。

ListView 将监听器注册到后备列表中,这样如果列表的内容发生变化,列表视图就会更新。

在ListView 中更改项目(两种不同的方式)

有两种方法可以更改ListView 显示的项目。您可以更改后备列表的内容。例如:

listView.getItems().setAll(someCollection);

将删除当前支持列表中的所有项目,并将它们替换为提供的集合中的所有项目。

或者,您可以完全提供新的支持列表:

listView.setItems(someObservableList);

这将告诉ListView 使用someObservableList 作为其支持列表。它将删除它在当前支持列表中注册的所有侦听器,将侦听器添加到您提供的列表中,您提供的列表的内容将成为列表视图的内容。

ListView 中的选定项目

选择模型通过listView.getSelectionModel().getSelectedItems() 公开一个包含列表中选定项目的ObservableList。当用户在列表视图中选择或取消选择项目时,ListView 会自动更新此列表。由于这是 @987654338 @,因此您可以在其内容更改时(即选择或取消选项时的内容时通知听众。

>>。。

你的代码做什么

所以在您提供的代码中:

listViewRight.setItems(listViewLeft.getSelectionModel().getSelectedItems());

这告诉listViewRight 使用来自listViewLeft 的选定项目列表作为其支持列表。 IE。如果listViewLeft.getSelectionModel().getSelectedItems() 的内容发生变化,那么ListView 的内容也会发生变化:这就是后备列表的目的。

另一方面,如果你这样做了

listViewRight.getItems().setAll(listViewLeft.getSelectionModel().getSelectedItems());

您将用listViewLeft 中的选定项目替换listViewRight 的当前支持列表的内容(即,您将清除支持列表并将listViewLeft 中的选定项目复制到支持列表中)。在这种情况下,对listViewLeft.getSelectionModel().getSelectedItems() 的后续更改将不会反映在listViewRight 的支持列表中。

【讨论】:

  • 如何在 ListView 的数据发生变化时更新数据库中的数据?意思是假设我更改了 List 的行,我如何只更新数据库中的那一行?我知道onChanged(ListChangedListener.Change),但我如何在数据库中更新它?假设我从数据库中获取名称并在 ListView 中显示它们。如果我将名称 A 更改为 B,那么如何在数据库中更新该名称?
【解决方案2】:

您应该阅读 (https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/ListView.html) 的 ListView JavaFX 8 文档。对于您的问题,请查看以下部分:

填充列表视图

此处显示了如何创建和填充名称(字符串)的 ListView 的简单示例:

ObservableList<String> names = FXCollections.observableArrayList("Julia", "Ian", "Sue", "Matthew", "Hannah", "Stephan", "Denise");
ListView<String> listView = new ListView<String>(names);

ListView 的元素包含在 ObservableList 项中。这个 ObservableList 会被 ListView 自动观察到,这样 ObservableList 内部发生的任何变化都会自动显示在 ListView 本身中。如果将 ObservableList 传递给 ListView 构造函数是不可行的,设置项目的推荐方法是简单地调用:

ObservableList<T> content = ...
listView.setItems(content);

如上所述,这样做的最终结果是 ListView 将自动刷新视图以表示列表中的项目。 另一种方法虽然被 ListView 接受,但不是推荐的方法:

List<T> content = ...
getItems().setAll(content);

所以你想要的是不是推荐的方法。为了你测试,改变你的代码

listViewRight.setItems(listViewLeft.getSelectionModel().getSelectedItems());

到

listViewRight.getItems().setAll(listViewLeft.getSelectionModel().getSelectedItems());

【讨论】:

  • 我已经阅读了文档。我想你没有仔细阅读我的问题。我说的是为什么 listViewRight 在调用 listViewLeft.getSelectionModel().getSelectedItems() 之后绑定到 ListViewLeft ?因为一旦我从 leftList 中选择了自动显示在 rightList 中的任何项目。
  • @Nothing 你用ObservableList 作为参数调用setItems。这样可以确保传播对此列表的任何修改,即更改左侧列表视图的选择会更改右侧的项目......这确实回答了这个问题,即使它可以更好地制定......
  • @fabian 随时帮助我 - 感谢您的承诺。
  • listViewLedt 确保listViewLeft.getSelectionModel().getSelectedItems() 返回的ObservableList 中的项目是选定的,并且此列表保持最新(否则返回一个 可观察列表)。使用setItems 将项目传递给listViewRight 确保该列表视图的项目始终是您作为参数传递的列表中的项目,即选择另一个列表视图...
  • FWIW 我认为文档通过调用getItems().setAll(...)“不是推荐的方法”超出了它的界限。该调用与setItems(...) 具有不同的功能,用户应该使用适合其要求的任何一个。 @Nothing 看起来您现在已经理解了它,但是没有人真正指出 listViewRight 的 items 列表未绑定到 listViewLeft.getSelectionModel().getSelectedItems():您的代码确保 listViewRight的items 列表是 listViewLeft 的selectedItems 列表。 IE。 它们是同一个列表。
猜你喜欢
  • 2012-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多