Saltar al contenido

Autocompletar ComboBox en JavaFX

Después de tanto trabajar ya encontramos el resultado de esta dificultad que tantos lectores de nuestro espacio presentan. Si deseas aportar algo más no dejes de dejar tu información.

Solución:

Primero, tendrás que crear esta clase en tu proyecto:

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 FxUtilTest 

    public interface AutoCompleteComparator 
        boolean matches(String typedText, T objectToCompare);
    

    public static void autoCompleteComboBoxPlus(ComboBox comboBox, AutoCompleteComparator comparatorMethod) 
        ObservableList data = comboBox.getItems();

        comboBox.setEditable(true);
        comboBox.getEditor().focusedProperty().addListener(observable -> 
            if (comboBox.getSelectionModel().getSelectedIndex() < 0) 
                comboBox.getEditor().setText(null);
            
        );
        comboBox.addEventHandler(KeyEvent.KEY_PRESSED, t -> comboBox.hide());
        comboBox.addEventHandler(KeyEvent.KEY_RELEASED, new EventHandler() 

            private boolean moveCaretToPos = false;
            private int caretPos;

            @Override
            public void handle(KeyEvent event)  event.getCode().equals(KeyCode.CONTROL)
                        

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

    public static T getComboBoxValue(ComboBox comboBox)
        if (comboBox.getSelectionModel().getSelectedIndex() < 0) 
            return null;
         else 
            return comboBox.getItems().get(comboBox.getSelectionModel().getSelectedIndex());
        
    


Para hacer tu ComboBox autocompletar, utilícelo así:

FxUtilTest.autoCompleteComboBoxPlus(myComboBox, (typedText, itemToCompare) -> itemToCompare.getName().toLowerCase().contains(typedText.toLowerCase()) || itemToCompare.getAge().toString().equals(typedText));

Luego, agregue un StringConverter como el siguiente ejemplo (porque el ComboBox el valor devolverá un String y tiene que convertirse en su objeto):

myComboBox.setConverter(new StringConverter<>() 

    @Override
    public String toString(YourObject object) 
        return object != null ? object.getName() : "";
    

    @Override
    public YourObject fromString(String string) 
        return myComboBox.getItems().stream().filter(object ->
                object.getName().equals(string)).findFirst().orElse(null);
    

);

También asegúrese de usar este método cuando necesite obtener el valor seleccionado del cuadro combinado, de lo contrario, puede enfrentar algunas excepciones como "excepción de conversión de clase":

FxUtilTest.getComboBoxValue(myComboBox);

PD: Hubo algunos problemas con este método en las versiones entre JRE 8.51 y 8.65 que causaron algunos comportamientos extraños, ahora los problemas parecen no ocurrir más. Si tiene algún problema, puede ver las ediciones realizadas en esta respuesta y obtener la versión anterior que solucionó el problema en ese momento. Este método debe funcionar bien, si tiene algún problema, hágamelo saber.

Encontré una solución que me funciona:

public class AutoCompleteComboBoxListener implements EventHandler 

    private ComboBox comboBox;
    private StringBuilder sb;
    private ObservableList 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() 

            @Override
            public void handle(KeyEvent t) 
                comboBox.hide();
            
        );
        this.comboBox.setOnKeyReleased(AutoCompleteComboBoxListener.this);
    

    @Override
    public void handle(KeyEvent event) 

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


Puedes llamarlo con

new AutoCompleteComboBoxListener<>(comboBox);

Se basa en esto y lo personalicé para satisfacer mis necesidades.

Siéntete libre de usarlo y si alguien puede mejorarlo, dímelo.

Con la biblioteca ControlsFX puedes hacerlo con dos líneas de código:

comboBox.setEditable(true);
TextFields.bindAutoCompletion(comboBox.getEditor(), comboBox.getItems());

Si guardas algún reparo o disposición de acrecentar nuestro post puedes escribir una observación y con gusto lo analizaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *