I am writing a generic Java class to display a list of filter items that can be un/checked and the resulting selection being then passed to a controller to filter the collection of primary objects for display. I'm using two ControlsFX controls: the PopOver
to contain the filter list and a CheckListView
to display and control the individual items.
The flow is that the filter PopOver
class is instantiated in the controller's constructor and the source data is reloaded every time it is shown.
On the surface the code appears to work. The source items are added, the checking and unchecking works and the number of items in the list of checked items is correct. However I've added listeners to the Observable Lists for both the source data and the list of checked items and neither is fired.
I've tried writing the listeners in-line and as separate methods (as in the example) and I've tried writing them in traditional onChanged
and lambda styles. Neither made a difference.
I've also tried using almost identical code just using theCheckListView
as a node of a pane. This did work exactly as expected.
I've also gone through the ControlsFX issues log and found nothing directly relevant (except to confirm that the code I was using seemed OK).
This is the Filter class:
package debuglogger;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.layout.BorderPane;
import org.controlsfx.control.CheckListView;
import org.controlsfx.control.PopOver;
public class FilterPopOverSO<T> extends PopOver {
private ObservableList<T> sourceData;
private BorderPane popoverNode;
private CheckListView<T> filterList;
/**
* ============================================================================================
* Constructor
* ============================================================================================
*/
public FilterPopOverSO() {
super();
sourceData = FXCollections.observableArrayList();
popoverNode = new BorderPane();
filterList = new CheckListView<>();
filterList.setPrefWidth(600D);
filterList.setMaxWidth(600D);
popoverNode.setCenter(filterList);
setContentNode(popoverNode);
filterList.getItems().addListener(sourceItemsListener);
filterList.getCheckModel().getCheckedItems().addListener(checkedItemsListener);
filterList.getCheckModel().checkAll();
}
/**
* ============================================================================================
* Listeners
* ============================================================================================
*/
ListChangeListener<T> sourceItemsListener = (change) -> {
System.out.println("Start of Change Listener 'sourceItemsListener'");
while(change.next()) {
System.out.println(" Added: " + change.wasAdded());
System.out.println(" Permutated: " + change.wasPermutated());
System.out.println(" Removed: " + change.wasRemoved());
System.out.println(" Updated: " + change.wasUpdated());
}
System.out.println("End of of Change Listener 'sourceItemsListener'");
};
ListChangeListener<T> checkedItemsListener = (change) -> {
System.out.println("Start of Change Listener 'checkedItemsListener'");
while(change.next()) {
System.out.println(" Added: " + change.wasAdded());
System.out.println(" Permutated: " + change.wasPermutated());
System.out.println(" Removed: " + change.wasRemoved());
System.out.println(" Updated: " + change.wasUpdated());
}
System.out.println("End of of Change Listener 'checkedItemsListener'");
};
public void setSourceData(ObservableList<T> sourceData) {
filterList.setItems(sourceData);
}
}
And this is the test stub:
package scratchpad;
import debuglogger.FilterPopOverSO;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class FilterPopOverTest extends Application {
@Override
public void start(Stage primaryStage) {
ObservableList<String> sourceList = FXCollections.observableArrayList("Item 1", "Item 2", "Item 3");
FilterPopOverSO<String> p = new FilterPopOverSO<>();
AnchorPane root = new AnchorPane();
Button btn = new Button("Click Me!");
btn.setOnAction(event -> {
System.out.println("Just to show that I was here!");
p.setSourceData(sourceList);
p.show(btn);
});
root.getChildren().add(btn);
AnchorPane.setTopAnchor(btn, 50D);
AnchorPane.setLeftAnchor(btn, 50D);
primaryStage.setTitle("Filter PopOver Test");
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}