制作自定义控制通用

时间:2016-12-07 22:19:03

标签: java generics javafx functional-programming javafx-8

我创建了一个自定义JavaFX控件,将其称为ComboBoxTablePopup,它是一个Generic Control,它从用户那里获取S类型的项目列表。 在内部,我在TableView(ComboboxTablePopup Contrl的一个孩子)中使用了某种过滤。所以我用过:

FiltredList.setPridcate(S -> {
            if (pr == null || pr.isEmpty() || pr.length() == 0)
                return true;
            if (((Engine) S).getDesignation().toLowerCase().contains(pr.toLowerCase())) {
                return true;
            } else
                return false;).

因为我正在使用泛型类,并且列表可以是任何类型,我必须将filtredlist项目转换为ordre中的已知对象以获得filtring工作。

那么,我怎样才能使谓词函数通用,所以我可以处理任何对象并过滤它?

以下是我的CustomControl的代码:

public class ComboBoxTablePopup<S> extends ComboBoxBase {

    private
    ObservableList<TableColumn> columns = FXCollections.emptyObservableList();

    public ObservableList<TableColumn> getColumns() {
        return columns;
    }

    public void setColumns(ObservableList<TableColumn> columns) {
        this.columns = columns;
    }




    /***************************************************************************
     * *
     * Static properties and methods                                           *
     * *
     **************************************************************************/

    private static <T> StringConverter<T> defaultStringConverter() {
        return new StringConverter<T>() {
            @Override
            public String toString(T t) {
                return t == null ? null : t.toString();
            }

            @Override
            public T fromString(String string) {
                return (T) string;
            }
        };
    }

    /***************************************************************************
     *                                                                         *
     * Constructors                                                            *
     *                                                                         *
     **************************************************************************/

    /**
     * Creates a default ComboboxTablePopup instance with an empty
     * {@link #itemsProperty() items} list and default
     * {@link #selectionModelProperty() selection model}.
     */


    public ComboBoxTablePopup() {
        this(FXCollections.<S>emptyObservableList());

    }


    /**
     * Creates a default ComboboxTablePopup instance with the provided items list and
     * a default {@link #selectionModelProperty() selection model}.
     */

    public ComboBoxTablePopup(ObservableList<S> items) {
        setItems(items);
        getStyleClass().add(DEFAULT_STYLE_CLASS);
        setEditable(true);
        setPromptText("Plz Search for a pirticular term");


    }

    public ComboBoxTablePopup(ObservableList<S> items, ObservableList<TableColumn> columns) {
        this(items);
        this.columns = columns;

    }


    private static final String DEFAULT_STYLE_CLASS = "combobox-table-popup";
    private ReadOnlyObjectWrapper<TextField> editor;

    private ObjectProperty<ObservableList<S>> items = new SimpleObjectProperty<ObservableList<S>>(this, "items");

    public final void setItems(ObservableList<S> value) {
        itemsProperty().set(value);
    }

    public final ObservableList<S> getItems() {
        return items.get();
    }

    public ObjectProperty<ObservableList<S>> itemsProperty() {
        return items;
    }


    // Converter
    public ObjectProperty<StringConverter<S>> converterProperty() {
        return converter;
    }

    private ObjectProperty<StringConverter<S>> converter =
            new SimpleObjectProperty<StringConverter<S>>(this, "converter", ComboBoxTablePopup.<S>defaultStringConverter());

    public final void setConverter(StringConverter<S> value) {
        converterProperty().set(value);
    }

    public final StringConverter<S> getConverter() {
        return converterProperty().get();
    }// Create a symmetric (format/parse) converter with the default locale.


    // Editor
    public TextField getEditor() {
        return editorProperty().get();
    }

    public ReadOnlyObjectProperty<TextField> editorProperty() {
        if (editor == null) {
            editor = new ReadOnlyObjectWrapper<TextField>(this, "editor");
            editor.set(new ComboBoxListViewSkin.FakeFocusTextField());

        }


        return editor.getReadOnlyProperty();

    }


    @Override
    protected Skin<?> createDefaultSkin() {
        return new ComboBoxTablePopupSkin<>(this);
    }


}
public class ComboBoxTablePopupSkin<S> extends ComboBoxPopupControl {

    private ComboBoxTablePopup comboBoxTablePopup;
    private ObservableList<S> comboboxTablePopupItems;

    private TextField displayNode;

    private TableView<S> tableViewPopupContent;


    FilteredList<S> filtredList;
    private SortedList<S> sortedList;

    private Predicate<S> predicate;

    private final InvalidationListener itemsObserver;

    private final ListChangeListener<S> tableViewItemsListener = new ListChangeListener<S>() {
        @Override
        public void onChanged(ListChangeListener.Change<? extends S> c) {
            getSkinnable().requestLayout();
        }
    };

    private final WeakListChangeListener<S> weakListViewItemsListener =
            new WeakListChangeListener<S>(tableViewItemsListener);

    public ComboBoxTablePopupSkin(ComboBoxTablePopup comboBoxTablePopup) {
        super(comboBoxTablePopup, new ComboBoxTablePopupBehavior(comboBoxTablePopup));
        this.comboBoxTablePopup = comboBoxTablePopup;

        setupTablePredicate();
        updateComboBoxTablePopupItems();


        itemsObserver = observable -> {
            updateComboBoxTablePopupItems();
            updateTableViewItems();

        };
        this.comboBoxTablePopup.itemsProperty().addListener(new WeakInvalidationListener(itemsObserver));

        tableViewPopupContent = createTableView();
        tableViewPopupContent.setManaged(false);

        getChildren().add(tableViewPopupContent);

        updateTableViewItems();


        getEditor().textProperty().addListener((obv, oldValue, newValue) -> {
            if (!newValue.isEmpty())
                comboBoxTablePopup.show();
            filtreData(newValue);
        });

        registerChangeListener(comboBoxTablePopup.itemsProperty(), "ITEMS");
        registerChangeListener(comboBoxTablePopup.valueProperty(), "VALUE");
        registerChangeListener(comboBoxTablePopup.editorProperty(), "EDITABLE");


    }

    private void setupTablePredicate() {

    }

    private void updateTableViewItems() {
        filtredList = new FilteredList<S>(comboboxTablePopupItems, p -> true);

        sortedList = new SortedList<S>(filtredList);

        sortedList.comparatorProperty().bind(tableViewPopupContent.comparatorProperty());
        tableViewPopupContent.setItems(sortedList);

    }

    private void filtreData(String pr) {
        String data = pr;
        filtredList.setPredicate(engine -> {
            if (pr == null || pr.isEmpty() || pr.length() == 0)
                return true;
            if (((Engine) engine).getDesignation().toLowerCase().contains(pr.toLowerCase())) {
                return true;
            } else
                return false;

        });


    }


    public void updateComboBoxTablePopupItems() {
        comboboxTablePopupItems = comboBoxTablePopup.getItems();
        comboboxTablePopupItems = comboboxTablePopupItems == null ? FXCollections.<S>emptyObservableList() : comboboxTablePopupItems;
    }

    private TableView<S> createTableView() {
        final TableView<S> tableView = new TableView<>();

        tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
        tableView.setFocusTraversable(false);

        tableView.getSelectionModel().selectedItemProperty().addListener(o -> {
            int index = tableView.getSelectionModel().getSelectedIndex();
            System.out.println("selected item changed");
        });

        for (TableColumn tblColumn : tableColumns()) {
            tableView.getColumns().add(tblColumn);
        }


        tableView.setOnKeyPressed(e -> {
            if (e.getCode() == KeyCode.ENTER ||
                    e.getCode() == KeyCode.ESCAPE ||
                    e.getCode() == KeyCode.SPACE) {
                S selectedItem = tableView.getSelectionModel().getSelectedItem();
                if (selectedItem != null) {

                    System.out.println(((Engine) selectedItem).getDesignation());
                    getEditor().setText(((Engine) selectedItem).getDesignation());
                    comboBoxTablePopup.setValue(selectedItem);
                    comboBoxTablePopup.hide();


                }
            }
        });


        return tableView;
    }

    private ObservableList<TableColumn> tableColumns() {
        return ((ComboBoxTablePopup) getSkinnable()).getColumns();
    }

    @Override
    protected Node getPopupContent() {
        return this.tableViewPopupContent;
    }

    @Override
    protected TextField getEditor() {
        return ((ComboBoxTablePopup) getSkinnable()).getEditor();
    }

    @Override
    protected StringConverter getConverter() {
        return ((ComboBoxTablePopup) getSkinnable()).getConverter();
    }

    @Override
    public Node getDisplayNode() {
        if (displayNode == null) {
            displayNode = getEditableInputNode();
            displayNode.getStylesheets().add("ComboBoxTable-display-node");
            updateDisplayNode();

        }

        displayNode.setEditable(comboBoxTablePopup.isEditable());


        return displayNode;


    }

    @Override
    protected void handleControlPropertyChanged(String p) {
        super.handleControlPropertyChanged(p);

        if ("TEXT".equals(p)) {
            if (!getEditor().textProperty().get().isEmpty()) {
                comboBoxTablePopup.show();
            }
            filtreData(getEditor().textProperty().get());

        } else if ("ITEMS".equals(p)) {
            updateComboBoxTablePopupItems();

        } else if ("EDITABLE".equals(p)) {
            getEditableInputNode();
        }

    }


}

1 个答案:

答案 0 :(得分:1)

使用StringConverter将商品转换为String或使用类似的商品。

public class ComboBoxTablePopupSkin<S> extends ComboBoxPopupControl<S> {

    ...

    private static final StringConverter DEFAULT_CONVERTER = new StringConverter() {

        @Override
        public String toString(Object o) {
            return o == null ? null : o.toString();
        }

        @Override
        public Object fromString(String s) {
            throw new UnsupportedOperationException();
        }
    };

    public final StringConverter<S> getConverter() {
        StringConverter<S> converter = converterProperty().get();
        // fix in case the property is set to a null
        return converter == null ? DEFAULT_CONVERTER : converter;
    }
private void filtreData(String pr) {
    if (pr == null || pr.isEmpty()) {
        filtredList.setPredicate(null);
    } else {
         final StringConverter<S> converter = ((ComboBoxTablePopup<S>) getSkinnable()).getConverter();

         final String data = pr.toLowerCase();
         filtredList.setPredicate(object -> {
            String s = converter.toString(object);
            return s != null && s.toLowerCase().contains(data);
         });
    }
}