I'm seeing something strange happen regarding the ListView control and selection changed events. I have a ListView, set to the MultiSelectModel.
The behavior I'm trying for is to be able to toggle selection on a row, such that if it's not selected it becomes selected , and if it already is selected it becomes un-selected. So I'm listening to two things: changes to the selectedItemProperty, and mousePress events:
list.getSelectionModel().selectedItemProperty().addListener(
new ChangeListener<Metadata>() {
public void changed(ObservableValue<? extends Metadata> ov,
Metadata old_val, Metadata new_val) {
System.out.println("Selection: " + new_val + ". Total list couunt=" + lists.length);
newSelection = true;
}
});
list.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
ObservableValue<? extends Metadata> ov =
hlist.getList().getSelectionModel().selectedItemProperty();
Metadata md = ov.getValue();
if ( newSelection == false ) {
ObservableList sl =
hlist.getList().getSelectionModel().getSelectedItems();
int index = hlist.getList().getSelectionModel().getSelectedIndex();
hlist.getList().getSelectionModel().clearSelection( index );
hlist.getList().getFocusModel().focus(-1);
//hlist.getList().getSelectionModel().clearSelection();
System.out.println( "Clearing selection in list: " +
attr + ", index: " + index +
", item: " + md.value );
return;
}
});
I have another listener that does something different when selection changes, and it needs to know when there are no more items selected. In this case, although the selected item is indeed un-selected, and the selectedItemProperty does change, there is no change event fired. I added test code to check the size of selectedItemProperty before and after the call to clearSelection(index) and it goes from 1 to 0. But no changed event is fired. However, if I replace clearSelection(index) with clearSelection(), I do get a changed event. I've added test code to prove that in both cases, selectedItemProperty ends up different, and with zero items in it. The secondary issue is that you cannot re-select the item that you just un-selected with clearSelection(index) either.
It's either an issue with clearSelection(index), or a misunderstanding on my part. I've included a complete sample application to illustrate. You can alter the behavior by locating the commented out line with clearSelection(), uncomment it, and comment out clearSelection(index). I'm running this on Windows XP. I verified the same behavior occurs on the Mac also.
Thanks,
Eric
/*
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
package listviewtest;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* @author ebruno1
*/
public class ListViewTest extends Application {
ListView list = new ListView();
ObservableList<String> data = FXCollections.observableArrayList(
"chocolate", "salmon", "gold", "coral", "darkorchid",
"darkgoldenrod", "lightsalmon", "black", "rosybrown", "blue",
"blueviolet", "brown");
boolean newSelection = false;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("ListViewTest");
VBox root = new VBox();
Scene scene = new Scene(root, 640, 480);
list.setItems(data);
// selection listener
list.getSelectionModel().selectedItemProperty().addListener(
new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> ov,
String old_val, String new_val) {
System.out.println("Selection changed: " + new_val );
newSelection = true;
}
});
// mouse pressed event
list.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
ObservableValue<? extends String> selProp =
list.getSelectionModel().selectedItemProperty();
String selItem = selProp.getValue();
if ( newSelection == false ) {
int index = list.getSelectionModel().getSelectedIndex();
// Test code: before
ObservableList sl = list.getSelectionModel().getSelectedItems();
System.out.println("BEFORE: Selection size="+sl.size());
if ( ! list.getSelectionModel().isSelected(index) )
System.out.println("**ERROR: Item is not selected **");
// Clear selection and focus
System.out.println( "Clearing selection index: " + index +
", item: " + selItem );
list.getSelectionModel().clearSelection( index );
//list.getSelectionModel().clearSelection();
list.getFocusModel().focus(-1);
// Test code: after
if ( list.getSelectionModel().isSelected(index) )
System.out.println("**ERROR: Item is STILL selected **");
sl = list.getSelectionModel().getSelectedItems();
System.out.println("AFTER: Selection size="+sl.size());
return;
}
newSelection = false;
}
});
root.getChildren().add(list);
VBox.setVgrow(list, Priority.ALWAYS);
primaryStage.setScene(scene);
primaryStage.show();
}
}
The behavior I'm trying for is to be able to toggle selection on a row, such that if it's not selected it becomes selected , and if it already is selected it becomes un-selected. So I'm listening to two things: changes to the selectedItemProperty, and mousePress events:
list.getSelectionModel().selectedItemProperty().addListener(
new ChangeListener<Metadata>() {
public void changed(ObservableValue<? extends Metadata> ov,
Metadata old_val, Metadata new_val) {
System.out.println("Selection: " + new_val + ". Total list couunt=" + lists.length);
newSelection = true;
}
});
list.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
ObservableValue<? extends Metadata> ov =
hlist.getList().getSelectionModel().selectedItemProperty();
Metadata md = ov.getValue();
if ( newSelection == false ) {
ObservableList sl =
hlist.getList().getSelectionModel().getSelectedItems();
int index = hlist.getList().getSelectionModel().getSelectedIndex();
hlist.getList().getSelectionModel().clearSelection( index );
hlist.getList().getFocusModel().focus(-1);
//hlist.getList().getSelectionModel().clearSelection();
System.out.println( "Clearing selection in list: " +
attr + ", index: " + index +
", item: " + md.value );
return;
}
});
I have another listener that does something different when selection changes, and it needs to know when there are no more items selected. In this case, although the selected item is indeed un-selected, and the selectedItemProperty does change, there is no change event fired. I added test code to check the size of selectedItemProperty before and after the call to clearSelection(index) and it goes from 1 to 0. But no changed event is fired. However, if I replace clearSelection(index) with clearSelection(), I do get a changed event. I've added test code to prove that in both cases, selectedItemProperty ends up different, and with zero items in it. The secondary issue is that you cannot re-select the item that you just un-selected with clearSelection(index) either.
It's either an issue with clearSelection(index), or a misunderstanding on my part. I've included a complete sample application to illustrate. You can alter the behavior by locating the commented out line with clearSelection(), uncomment it, and comment out clearSelection(index). I'm running this on Windows XP. I verified the same behavior occurs on the Mac also.
Thanks,
Eric
/*
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
package listviewtest;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* @author ebruno1
*/
public class ListViewTest extends Application {
ListView list = new ListView();
ObservableList<String> data = FXCollections.observableArrayList(
"chocolate", "salmon", "gold", "coral", "darkorchid",
"darkgoldenrod", "lightsalmon", "black", "rosybrown", "blue",
"blueviolet", "brown");
boolean newSelection = false;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("ListViewTest");
VBox root = new VBox();
Scene scene = new Scene(root, 640, 480);
list.setItems(data);
// selection listener
list.getSelectionModel().selectedItemProperty().addListener(
new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> ov,
String old_val, String new_val) {
System.out.println("Selection changed: " + new_val );
newSelection = true;
}
});
// mouse pressed event
list.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
ObservableValue<? extends String> selProp =
list.getSelectionModel().selectedItemProperty();
String selItem = selProp.getValue();
if ( newSelection == false ) {
int index = list.getSelectionModel().getSelectedIndex();
// Test code: before
ObservableList sl = list.getSelectionModel().getSelectedItems();
System.out.println("BEFORE: Selection size="+sl.size());
if ( ! list.getSelectionModel().isSelected(index) )
System.out.println("**ERROR: Item is not selected **");
// Clear selection and focus
System.out.println( "Clearing selection index: " + index +
", item: " + selItem );
list.getSelectionModel().clearSelection( index );
//list.getSelectionModel().clearSelection();
list.getFocusModel().focus(-1);
// Test code: after
if ( list.getSelectionModel().isSelected(index) )
System.out.println("**ERROR: Item is STILL selected **");
sl = list.getSelectionModel().getSelectedItems();
System.out.println("AFTER: Selection size="+sl.size());
return;
}
newSelection = false;
}
});
root.getChildren().add(list);
VBox.setVgrow(list, Priority.ALWAYS);
primaryStage.setScene(scene);
primaryStage.show();
}
}