JavaFX ListChangedListeners不使用ControlsFX PopOver和CheckListView触发

时间:2021-01-27 05:28:42

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.

我正在编写一个通用Java类来显示可以取消/检查的过滤器项列表,然后将结果选择传递给控制器​​以过滤主要对象的集合以供显示。我正在使用两个ControlsFX控件:PopOver包含筛选器列表和CheckListView以显示和控制各个项目。

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.

流程是过滤器PopOver类在控制器的构造函数中实例化,并且每次显示源数据时都会重新加载源数据。

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.

从表面上看,代码似乎有效。添加源项目,检查和取消选中工作以及已检查项目列表中的项目数是否正确。但是我已经为源数据和已检查项列表添加了Observable Lists的监听器,并且都没有被触发。

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.

我尝试在线编写监听器,并作为单独的方法(如示例中所示),我尝试用传统的onChanged和lambda样式编写它们。两者都没有区别。我也尝试使用几乎相同的代码,只使用CheckListView作为窗格的节点。这确实按预期工作。

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).

我也经历了ControlsFX问题日志,发现没有直接相关的(除了确认我使用的代码似乎没问题)。

This is the Filter class:

这是Filter类:

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);
}
}

1 个解决方案

#1


Problem solved. The garbage collector was removing the listeners every time the popover was hidden. I simply moved the 'add listener' statement to the point where I showed the popover.

问题解决了。每次隐藏弹出窗口时,垃圾收集器都会删除侦听器。我只是将'添加侦听器'语句移动到我显示弹出窗口的位置。

#1


Problem solved. The garbage collector was removing the listeners every time the popover was hidden. I simply moved the 'add listener' statement to the point where I showed the popover.

问题解决了。每次隐藏弹出窗口时,垃圾收集器都会删除侦听器。我只是将'添加侦听器'语句移动到我显示弹出窗口的位置。