JavaFX ListView selectedItemProperty 未触发 clearSelection(index)
JavaFX ListView selectedItemProperty not firing on clearSelection(index)
我将 JavaFX 用于我正在编写的应用程序的 GUI。我的 GUI 中有一个 ListView 和一个 Button。
我希望 ListView 在鼠标单击时保持多项选择,并且仅在再次单击时删除选择(这有效)。
我还需要验证是否已在 ListView 中选择了某些内容,如果未启用任何内容,则禁用该按钮(适用于选择但不适用于取消选择)。
这是我启用和禁用按钮的代码(这不起作用):
//Binding used to enable and disable the button
BooleanBinding validEntriesBinding = new BooleanBinding(){
{
super.bind(listView.getSelectionModel().selectedItemProperty());
}
@Override
protected boolean computeValue() {
log.info("No individual item selected? " +
(listView.getSelectionModel().getSelectedItems().isEmpty()));
log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
return (listView.getSelectionModel().getSelectedItems().isEmpty());
}
};
button.disableProperty().bind(validEntriesBinding);
这是我用于捕获鼠标选择的代码(这是有效的,解决方案是根据 SO fabian 的回答开发的):
//Example sourced from whosebug.com/questions/40900478/mimicking-ctrlclick-multiple-selection-in-listview-using-javafx
//Answer by fabian
//Must use MouseEvent.MOUSE_PRESSED and not MOUSE_CLICKED, otherwise the selection does not work
listView.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
Node node = event.getPickResult().getIntersectedNode();
while(node != null && node != listView && !(node instanceof ListCell)){
node = node.getParent();
}
if(node instanceof ListCell){
event.consume();
listView.requestFocus();
ListCell cell = (ListCell) node;
if(!cell.isEmpty()){
if(cell.isSelected()){
log.info("Clear selection...");
listView.getSelectionModel().clearSelection(cell.getIndex());
log.info("Selection cleared");
}
else{
log.info("Selecting...");
listView.getSelectionModel().select(cell.getIndex());
log.info("Selected");
}
}
else{
log.warn("Cell is empty... cannot select");
}
}
else{
log.warn("Unable to handle event for " + node.getId() + " " + node.getClass());
}
});
这是我 运行 我的应用程序时的输出:
//Before click, button disabled
No individual item selected? true
Selected items: []
//First click selecting a cell, button enabled
Selecting...
No individual item selected? false
Selected items: [SV124]
Selected
//Second click deselecting the first selected cell, button stays
//enabled as the BooleanBinding never fires
Clear selection...
Selection cleared
为什么 BooleanBinding
没有在 listView.getSelectionModel().clearSelection(cell.getIndex());
上触发?或者,更直接地说,为什么 listView.getSelectionModel().selectedItemProperty()
在选择为空时不触发?根据 Javadoc,它应该 return null 空的时候,所以不应该被捕获吗?
从列表视图的选择模型中删除选定的 index 似乎无法使 selectedItemProperty()
无效。 (这似乎是一个错误。)
如果您绑定到 selectedIndexProperty
而不是 selectedItemProperty
,它会起作用:
BooleanBinding validEntriesBinding = new BooleanBinding(){
{
super.bind(listView.getSelectionModel().selectedIndexProperty());
}
@Override
protected boolean computeValue() {
log.info("No individual item selected? " +
(listView.getSelectionModel().getSelectedItems().isEmpty()));
log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
return (listView.getSelectionModel().getSelectedItems().isEmpty());
}
};
也许,因为您启用了多项选择,所以无论如何最好绑定到所选项目的列表:
BooleanBinding validEntriesBinding = new BooleanBinding(){
{
super.bind(listView.getSelectionModel().getSelectedItems());
}
@Override
protected boolean computeValue() {
log.info("No individual item selected? " +
(listView.getSelectionModel().getSelectedItems().isEmpty()));
log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
return (listView.getSelectionModel().getSelectedItems().isEmpty());
}
};
注意如果把validEntriesBinding
设为局部变量,容易出现accidental garbage collection。你应该把它改成一个字段:
private BooleanBinding validEntriesBinding ;
// ...
validEntriesBinding = new BooleanBinding(){
{
super.bind(listView.getSelectionModel().getSelectedItems());
}
@Override
protected boolean computeValue() {
log.info("No individual item selected? " +
(listView.getSelectionModel().getSelectedItems().isEmpty()));
log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
return (listView.getSelectionModel().getSelectedItems().isEmpty());
}
};
我将 JavaFX 用于我正在编写的应用程序的 GUI。我的 GUI 中有一个 ListView 和一个 Button。
我希望 ListView 在鼠标单击时保持多项选择,并且仅在再次单击时删除选择(这有效)。
我还需要验证是否已在 ListView 中选择了某些内容,如果未启用任何内容,则禁用该按钮(适用于选择但不适用于取消选择)。
这是我启用和禁用按钮的代码(这不起作用):
//Binding used to enable and disable the button
BooleanBinding validEntriesBinding = new BooleanBinding(){
{
super.bind(listView.getSelectionModel().selectedItemProperty());
}
@Override
protected boolean computeValue() {
log.info("No individual item selected? " +
(listView.getSelectionModel().getSelectedItems().isEmpty()));
log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
return (listView.getSelectionModel().getSelectedItems().isEmpty());
}
};
button.disableProperty().bind(validEntriesBinding);
这是我用于捕获鼠标选择的代码(这是有效的,解决方案是根据
//Example sourced from whosebug.com/questions/40900478/mimicking-ctrlclick-multiple-selection-in-listview-using-javafx
//Answer by fabian
//Must use MouseEvent.MOUSE_PRESSED and not MOUSE_CLICKED, otherwise the selection does not work
listView.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
Node node = event.getPickResult().getIntersectedNode();
while(node != null && node != listView && !(node instanceof ListCell)){
node = node.getParent();
}
if(node instanceof ListCell){
event.consume();
listView.requestFocus();
ListCell cell = (ListCell) node;
if(!cell.isEmpty()){
if(cell.isSelected()){
log.info("Clear selection...");
listView.getSelectionModel().clearSelection(cell.getIndex());
log.info("Selection cleared");
}
else{
log.info("Selecting...");
listView.getSelectionModel().select(cell.getIndex());
log.info("Selected");
}
}
else{
log.warn("Cell is empty... cannot select");
}
}
else{
log.warn("Unable to handle event for " + node.getId() + " " + node.getClass());
}
});
这是我 运行 我的应用程序时的输出:
//Before click, button disabled
No individual item selected? true
Selected items: []
//First click selecting a cell, button enabled
Selecting...
No individual item selected? false
Selected items: [SV124]
Selected
//Second click deselecting the first selected cell, button stays
//enabled as the BooleanBinding never fires
Clear selection...
Selection cleared
为什么 BooleanBinding
没有在 listView.getSelectionModel().clearSelection(cell.getIndex());
上触发?或者,更直接地说,为什么 listView.getSelectionModel().selectedItemProperty()
在选择为空时不触发?根据 Javadoc,它应该 return null 空的时候,所以不应该被捕获吗?
从列表视图的选择模型中删除选定的 index 似乎无法使 selectedItemProperty()
无效。 (这似乎是一个错误。)
如果您绑定到 selectedIndexProperty
而不是 selectedItemProperty
,它会起作用:
BooleanBinding validEntriesBinding = new BooleanBinding(){
{
super.bind(listView.getSelectionModel().selectedIndexProperty());
}
@Override
protected boolean computeValue() {
log.info("No individual item selected? " +
(listView.getSelectionModel().getSelectedItems().isEmpty()));
log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
return (listView.getSelectionModel().getSelectedItems().isEmpty());
}
};
也许,因为您启用了多项选择,所以无论如何最好绑定到所选项目的列表:
BooleanBinding validEntriesBinding = new BooleanBinding(){
{
super.bind(listView.getSelectionModel().getSelectedItems());
}
@Override
protected boolean computeValue() {
log.info("No individual item selected? " +
(listView.getSelectionModel().getSelectedItems().isEmpty()));
log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
return (listView.getSelectionModel().getSelectedItems().isEmpty());
}
};
注意如果把validEntriesBinding
设为局部变量,容易出现accidental garbage collection。你应该把它改成一个字段:
private BooleanBinding validEntriesBinding ;
// ...
validEntriesBinding = new BooleanBinding(){
{
super.bind(listView.getSelectionModel().getSelectedItems());
}
@Override
protected boolean computeValue() {
log.info("No individual item selected? " +
(listView.getSelectionModel().getSelectedItems().isEmpty()));
log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
return (listView.getSelectionModel().getSelectedItems().isEmpty());
}
};