java - 将过滤后的组合框项链接到输入

标签 java javafx combobox javafx-8

在我的可编辑组合框中,根据输入过滤我的建议,我可以触发 Button 事件。问题是,如果我在可编辑字段中输入我的项目名称之一(例如 action3),然后单击第一个建议(也将是 action3),是合适的项目,它总是用第一个索引 action1 触发 ButtonEvent,因为它有第一个索引,但第一个索引是 action1

List<EventHandler<ActionEvent>> handlers = Arrays.asList(
            this::action1,
            this::action2,
            this::action3
            );

那么我如何像action1一样链接到我的建议正确的建议?

public void onEnter(ActionEvent event){
    int index = editableComboBox.getSelectionModel().getSelectedIndex();
    if (index >= 0) {
         handlers.get(index).handle(event);
    }

}

编辑1:

我的新的initialize()方法如下所示:

protected void initialize() {
    new AutoCompleteBox<>(autoBox);     
    ObservableList<ActionEventHandler> data = FXCollections.observableArrayList(
            new ActionEventHandler("action1", this::action1),
            new ActionEventHandler("action2", this::action2,
            new ActionEventHandler("action3", this::action3)
    );
    autoBox.getItems().setAll(data);
    FilteredList<ActionEventHandler> filtered = new FilteredList<>(data);
    ComboBox<ActionEventHandler> autoBox = new ComboBox<>(filtered);
    autoBox.setOnAction(event -> {
        ActionEventHandler h = autoBox.getValue();
        if (h != null) {
            h.handle(event);
        }
    });
    autoBox.setEditable(true);
    autoBox.setConverter(new StringConverter<ActionEventHandler>() {

        @Override
        public String toString(ActionEventHandler object) {
            return object == null ? "" : object.toString();
        }

        @Override
        public ActionEventHandler fromString(String string) {
            if (string == null) {
                return null;
            }
            for (ActionEventHandler h : data) {
                if (string.equals(h.toString())) {
                    return h;
                }
            }
            return null;
        }

    });

    autoBox.getEditor().textProperty().addListener((observable, oldValue, newValue) -> {
        filtered.setPredicate(h -> h.toString().startsWith(newValue));
    });

}

以及自定义ComboBox类:

public class AutoCompleteBox<T> implements EventHandler<KeyEvent> {

    private ComboBox comboBox;
    private StringBuilder sb;
    private ObservableList<T> data;
    private boolean moveCaretToPos = false;
    private int caretPos; 

    public AutoCompleteBox(final ComboBox comboBox) {
        this.comboBox = comboBox;
        sb = new StringBuilder();      
        data = comboBox.getItems();



        this.comboBox.setEditable(true);
        this.comboBox.setOnKeyPressed(new EventHandler<KeyEvent>() {

            @Override
            public void handle(KeyEvent t) {
                comboBox.hide();
            }
        });
        this.comboBox.setOnKeyReleased(AutoCompleteBox.this);
    }

    @Override
    public void handle(KeyEvent event) {

        if(event.getCode() == KeyCode.UP) {
            caretPos = -1;
            moveCaret(comboBox.getEditor().getText().length());
            return;
        } else if(event.getCode() == KeyCode.DOWN) {
            if(!comboBox.isShowing()) {
                comboBox.show();
            }
            caretPos = -1;
            moveCaret(comboBox.getEditor().getText().length());
            return;
        } else if(event.getCode() == KeyCode.BACK_SPACE) {
            moveCaretToPos = true;
            caretPos = comboBox.getEditor().getCaretPosition();
        } else if(event.getCode() == KeyCode.DELETE) {
            moveCaretToPos = true;
            caretPos = comboBox.getEditor().getCaretPosition();
        }

        if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT
                || event.isControlDown() || event.getCode() == KeyCode.HOME
                || event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) {
            return;
        }

        ObservableList list = FXCollections.observableArrayList();
        for (int i=0; i<data.size(); i++) {
            if(data.get(i).toString().toLowerCase().startsWith(
                    AutoCompleteBox.this.comboBox
                .getEditor().getText().toLowerCase())) {
                list.add(data.get(i));
            }
        }
        String t = comboBox.getEditor().getText();

        comboBox.setItems(list);
        comboBox.getEditor().setText(t);
        if(!moveCaretToPos) {
            caretPos = -1;
        }
        moveCaret(t.length());
        if(!list.isEmpty()) {
            comboBox.show();
        }
    }

    private void moveCaret(int textLength) {
        if(caretPos == -1) {
            comboBox.getEditor().positionCaret(textLength);
        } else {
            comboBox.getEditor().positionCaret(caretPos);
        }
        moveCaretToPos = false;
    }
}

我无法链接函数(例如 action1 到字符串 action1),或者我更相信的是,我无法将自定义类与我的自定义 组合框

最佳答案

在这种情况下,似乎最好使用 EventHandler<ActionEvent> s 作为返回 toString 字符串的项目。添加converter将项目转换为非 String对象。

public class ActionEventHandler implements EventHandler<ActionEvent> {

    private final EventHandler<ActionEvent> eventHandler;
    private final String name;

    public ActionEventHandler(String name, EventHandler<ActionEvent> eventHandler) {
        Objects.requireNonNull(name);
        Objects.requireNonNull(eventHandler);
        this.name = name;
        this.eventHandler = eventHandler;
    }

    @Override
    public String toString() {
        return name;
    }

    @Override
    public void handle(ActionEvent event) {
        eventHandler.handle(event);
    }

}
ObservableList<ActionEventHandler> data = FXCollections.observableArrayList(
        new ActionEventHandler("action1", this::action1),
        new ActionEventHandler("action2", this::action2),
        new ActionEventHandler("action3", this::action3)
);
FilteredList<ActionEventHandler> filtered = new FilteredList<>(data);
ComboBox<ActionEventHandler> comboBox = new ComboBox<>(filtered);
comboBox.setOnAction(event -> {
    ActionEventHandler h = comboBox.getValue();
    if (h != null) {
        h.handle(event);
    }
});
comboBox.setEditable(true);
comboBox.setConverter(new StringConverter<ActionEventHandler>() {

    @Override
    public String toString(ActionEventHandler object) {
        return object == null ? "" : object.toString();
    }

    @Override
    public ActionEventHandler fromString(String string) {
        if (string == null) {
            return null;
        }
        for (ActionEventHandler h : data) {
            if (string.equals(h.toString())) {
                return h;
            }
        }
        return null;
    }

});
comboBox.getEditor().textProperty().addListener((observable, oldValue, newValue) -> {
    filtered.setPredicate(h -> h.toString().startsWith(newValue));
});
<小时/>

编辑

以下代码应该与您的 AutoCompleteBox 一起使用类。

@FXML
private ComboBox<ActionEventHandler> autoBox;

@FXML
private void initialize() {
    autoBox.getItems().setAll(
            new ActionEventHandler("action1", this::action1),
            new ActionEventHandler("action2", this::action2),
            new ActionEventHandler("action3", this::action3));
    autoBox.setOnAction(event -> {
        ActionEventHandler h = autoBox.getValue();
        if (h != null) {
            h.handle(event);
        }
    });
    autoBox.setConverter(new StringConverter<ActionEventHandler>() {

        @Override
        public String toString(ActionEventHandler object) {
            return object == null ? "" : object.toString();
        }

        @Override
        public ActionEventHandler fromString(String string) {
            if (string == null) {
                return null;
            }
            for (ActionEventHandler h : autoBox.getItems()) {
                if (string.equals(h.toString())) {
                    return h;
                }
            }
            return null;
        }

    });
    new AutoCompleteBox<>(autoBox);
}

(不过我还没有检查您的 AutoCompleteBox 类(class)的详细信息...)

关于java - 将过滤后的组合框项链接到输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40608292/

相关文章:

java - 如何将 JavaFXML 中的各个表格列标题与 CSS 对齐

java.net.BindException : Address already in use: bind - when stating tomcatx with jdk1. 8(未处于 Debug模式)

javascript - 焦点事件 jquery 组合框/自动完成

.NET Windows 窗体 datagridview - 必须单击组合框列三次才能获得焦点

java - 是否可以制作 JavaFX web 小程序?

c# - WPF 组合框默认值(请选择)

java - 随机排列按钮 android

java - JNI 中的 UnsatisfiedLinkError

JavaFX VBox 一行上有多个元素

javafx - 如何以编程方式在 WebView 中使用基本身份验证 - JavaFX