带有 ChangeListener 的 JavaFX TableView 用于多选
JavaFX TableView with ChangeListener for multiple selection
我想监听 JavaFX 8 中 table 视图上的 selection 变化。如果我将 ChangeListener 添加到 selectedItemProperty
(或 selectedIndex属性) 的 MultipleSelectionModel 在以下情况下它不会触发:
多行已经 selected,现在我 select 一个新的单行。如果这一行是之前被select编辑过的最后一行,它不会做出反应。这是因为 selectedItem属性 只包含一项,而不是所有 selected 的列表。但不幸的是,没有 selectedItems属性 这很奇怪,因为方法 getSelectedItems()
存在。我不知道在哪里添加侦听器以使其在任何情况下都能正常工作。
这是一个示例代码:
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MultipleSelectionTest extends Application
{
private ListView<Integer> list = new ListView<>();
private TableView<String> table = new TableView<>();
private TableColumn<String, String> column1 = new TableColumn<>("Numbers");
@Override
public void start(Stage primaryStage) throws Exception
{
HBox box = new HBox(list, table);
primaryStage.setScene(new Scene(box, 300, 500));
initializeTable();
initializeList();
primaryStage.show();
}
private void initializeTable()
{
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
table.getColumns().add(column1);
column1.setCellValueFactory(s -> new SimpleStringProperty(s.getValue()));
table.setItems(FXCollections.observableArrayList("One", "Two", "Three", "Four", "Five", "Six", "Seven"));
}
private void initializeList()
{
table.getSelectionModel().selectedItemProperty().addListener((property, oldValue, newValue) ->
{
ObservableList<Integer> convertedItems = FXCollections.observableList(
table.getSelectionModel().getSelectedItems()
.stream()
.map(this::convertNumber)
.collect(Collectors.toList()));
list.setItems(convertedItems);
});
}
private int convertNumber(String expression)
{
switch (expression)
{
case "One": return 1;
case "Two": return 2;
case "Three": return 3;
case "Four": return 4;
case "Five": return 5;
case "Six": return 6;
case "Seven": return 7;
default: throw new IllegalArgumentException();
}
}
public static void main(String[] args)
{
launch();
}
}
请注意,此示例中的 ListView 仅用于视觉目的。
您不需要 selectedItemsProperty
- getSelectedItems
returns 和 ObservableList
来添加侦听器。
为此设置 属性 意味着列表对象已更改,但实际上列表保持不变 对象,但其内容已更改。
这里有一个更完整的解决方案,感谢 SillyFly 的回复中的指针。
在我的示例中,假设 table 设置为与任意 class 人一起工作,该人定义了名字、姓氏和电子邮件。
//Set the table to multi selection mode
table.getSelectionModel().setSelectionMode( SelectionMode.MULTIPLE);
//Regiseter the listener on the ObervableList<Person>
table.getSelectionModel().getSelectedItems().addListener(multiSelection);
/**A listener for list selections, multiple selections in the TableView**/
ListChangeListener< Person> multiSelection = new ListChangeListener<Person>(){
@Override
public void onChanged( ListChangeListener.Change<? extends Person> changed){
for( Person p : changed.getList())
System.out.println(p);
}
};
我想监听 JavaFX 8 中 table 视图上的 selection 变化。如果我将 ChangeListener 添加到 selectedItemProperty
(或 selectedIndex属性) 的 MultipleSelectionModel 在以下情况下它不会触发:
多行已经 selected,现在我 select 一个新的单行。如果这一行是之前被select编辑过的最后一行,它不会做出反应。这是因为 selectedItem属性 只包含一项,而不是所有 selected 的列表。但不幸的是,没有 selectedItems属性 这很奇怪,因为方法 getSelectedItems()
存在。我不知道在哪里添加侦听器以使其在任何情况下都能正常工作。
这是一个示例代码:
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MultipleSelectionTest extends Application
{
private ListView<Integer> list = new ListView<>();
private TableView<String> table = new TableView<>();
private TableColumn<String, String> column1 = new TableColumn<>("Numbers");
@Override
public void start(Stage primaryStage) throws Exception
{
HBox box = new HBox(list, table);
primaryStage.setScene(new Scene(box, 300, 500));
initializeTable();
initializeList();
primaryStage.show();
}
private void initializeTable()
{
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
table.getColumns().add(column1);
column1.setCellValueFactory(s -> new SimpleStringProperty(s.getValue()));
table.setItems(FXCollections.observableArrayList("One", "Two", "Three", "Four", "Five", "Six", "Seven"));
}
private void initializeList()
{
table.getSelectionModel().selectedItemProperty().addListener((property, oldValue, newValue) ->
{
ObservableList<Integer> convertedItems = FXCollections.observableList(
table.getSelectionModel().getSelectedItems()
.stream()
.map(this::convertNumber)
.collect(Collectors.toList()));
list.setItems(convertedItems);
});
}
private int convertNumber(String expression)
{
switch (expression)
{
case "One": return 1;
case "Two": return 2;
case "Three": return 3;
case "Four": return 4;
case "Five": return 5;
case "Six": return 6;
case "Seven": return 7;
default: throw new IllegalArgumentException();
}
}
public static void main(String[] args)
{
launch();
}
}
请注意,此示例中的 ListView 仅用于视觉目的。
您不需要 selectedItemsProperty
- getSelectedItems
returns 和 ObservableList
来添加侦听器。
为此设置 属性 意味着列表对象已更改,但实际上列表保持不变 对象,但其内容已更改。
这里有一个更完整的解决方案,感谢 SillyFly 的回复中的指针。
在我的示例中,假设 table 设置为与任意 class 人一起工作,该人定义了名字、姓氏和电子邮件。
//Set the table to multi selection mode
table.getSelectionModel().setSelectionMode( SelectionMode.MULTIPLE);
//Regiseter the listener on the ObervableList<Person>
table.getSelectionModel().getSelectedItems().addListener(multiSelection);
/**A listener for list selections, multiple selections in the TableView**/
ListChangeListener< Person> multiSelection = new ListChangeListener<Person>(){
@Override
public void onChanged( ListChangeListener.Change<? extends Person> changed){
for( Person p : changed.getList())
System.out.println(p);
}
};