使用Javafx自动完成具有ID和值对的ComboBox

时间:2016-03-11 03:55:49

标签: javafx combobox javafx-2 javafx-8

我已尝试使用以下代码创建具有ID和值的自动完成组合框。当我使用鼠标事件选择任何值时,它工作正常。但是使用Key Event它会显示错误

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.String cannot be cast to demo.Demo$Employee
at demo.Demo$1.changed(Demo.java:34) 

代码:AutoCompleteComboBoxListener.java

package demo;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.control.ComboBox;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

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

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

    public AutoCompleteComboBoxListener(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(AutoCompleteComboBoxListener.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(
                AutoCompleteComboBoxListener.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;
    }

}

代码:Demo.java

package demo;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

/**
 *
 * @author vikassingh
 */
public class Demo extends Application {

    private final ObservableList<Employee> data
            = FXCollections.observableArrayList(
                    new Employee("Azamat", 2200.15),
                    new Employee("Veli", 1400.0),
                    new Employee("Nurbek", 900.5));

    @Override
    public void start(Stage primaryStage) {
        ComboBox<Employee> combobox = new ComboBox<>(data);
        new AutoCompleteComboBoxListener<>(combobox);
        combobox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Employee>() {

            @Override
            public void changed(ObservableValue<? extends Employee> arg0, Employee arg1, Employee arg2) {
                if (arg2 != null) {
                    System.out.println("Selected employee: " + arg2.getName());
                    System.out.println("Salary: " + arg2.getSalary());
                }
            }
        });
        StackPane root = new StackPane();
        root.getChildren().add(combobox);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }

    public static class Employee {

        private String name;
        private Double salary;

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

        public Employee(String name, Double salary) {
            this.name = name;
            this.salary = salary;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Double getSalary() {
            return salary;
        }

        public void setSalary(Double salary) {
            this.salary = salary;
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

1 个答案:

答案 0 :(得分:0)

使用以下start()方法替换start()方法并理解代码。

public void start(Stage primaryStage) {
        ComboBox<Employee> combobox = new ComboBox<>(data);
        new AutoCompleteComboBoxListener<>(combobox);
        combobox.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("Selected employee: " + combobox.getSelectionModel().getSelectedItem());
                System.out.println("Salary: " + combobox.getSelectionModel().getSelectedItem().getSalary());
            }
        });

        combobox.setConverter(new StringConverter<Employee>() {

            @Override
            public String toString(Employee object) {
                if (object == null) return null;
                return object.toString();
            }

            @Override
            public Employee fromString(String string) {
                Employee employee = new Employee();
                for(Employee emp : combobox.getItems()){
                    if(emp.getName().equals(string)){
                        employee = emp;
                        break;
                    }
                }
                return employee;
            }
        });


        StackPane root = new StackPane();
        root.getChildren().add(combobox);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }

由于您在comboBox中使用了editable true,因此您需要调用上面代码中给出的combobox.setconverter()函数。 我希望它会对你有所帮助。