Saltar al contenido

Cree un cuadro de texto de autocompletado en Java con una lista desplegable

Posterior a de una prolongada selección de información hemos podido solucionar esta contrariedad que suelen tener muchos los lectores. Te ofrecemos la solución y nuestro deseo es resultarte de mucha ayuda.

La respuesta de @ syb0rg es más fácil, ya que utiliza una biblioteca de terceros.

Sin embargo, utilicé un enfoque alternativo:

Utiliza una clase personalizada llamada AutoSuggestor que acepta un JTextField, su Window un ArrayList de palabras para comparar las palabras escritas, un color de fondo y color de texto, y un color de enfoque de sugerencia, así como un valor de opacidad. Pasando JTextField referencia a DocumentListener Se agrega que hará el trabajo de verificar qué palabra se escribe y si mostrar sugerencias o no y, de ser así, qué sugerencias mostrar. Cuando se escribe una palabra, DocumentListener dispararáwordTyped(String wordTyped) método con la palabra actual que se está escribiendo o (al menos la cantidad de la palabra que se ha escrito), en wordTyped(..) la palabra se comparará con las del AutoSuggestors clases diccionario que es un básico ArrayList de String esto se puede configurar sobre la marcha como se ve en el siguiente ejemplo:

ingrese la descripción de la imagen aquí

(Por ahora, tendrá que usar el mouse y hacer clic en la palabra que desea que se complete automáticamente, o usar ABAJO a sugerencias transversales y el campo de texto y INGRESAR para seleccionar la sugerencia al atravesar usando abajo key. Todavía no he implementado HASTA todavía):

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

/**
 * @author David
 */
public class Test 

    public Test() 

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        JTextField f = new JTextField(10);

        AutoSuggestor autoSuggestor = new AutoSuggestor(f, frame, null, Color.WHITE.brighter(), Color.BLUE, Color.RED, 0.75f) 
            @Override
            boolean wordTyped(String typedWord) 

                //create list for dictionary this in your case might be done via calling a method which queries db and returns results as arraylist
                ArrayList words = new ArrayList<>();
                words.add("hello");
                words.add("heritage");
                words.add("happiness");
                words.add("goodbye");
                words.add("cruel");
                words.add("car");
                words.add("war");
                words.add("will");
                words.add("world");
                words.add("wall");


                setDictionary(words);
                //addToDictionary("bye");//adds a single word

                return super.wordTyped(typedWord);//now call super to check for any matches against newest dictionary
            
        ;

        JPanel p = new JPanel();

        p.add(f);

        frame.add(p);

        frame.pack();
        frame.setVisible(true);
    

    public static void main(String[] args) 
        SwingUtilities.invokeLater(new Runnable() 
            @Override
            public void run() 
                new Test();
            
        );
    


class AutoSuggestor 

    private final JTextField textField;
    private final Window container;
    private JPanel suggestionsPanel;
    private JWindow autoSuggestionPopUpWindow;
    private String typedWord;
    private final ArrayList dictionary = new ArrayList<>();
    private int currentIndexOfSpace, tW, tH;
    private DocumentListener documentListener = new DocumentListener() 
        @Override
        public void insertUpdate(DocumentEvent de) 
            checkForAndShowSuggestions();
        

        @Override
        public void removeUpdate(DocumentEvent de) 
            checkForAndShowSuggestions();
        

        @Override
        public void changedUpdate(DocumentEvent de) 
            checkForAndShowSuggestions();
        
    ;
    private final Color suggestionsTextColor;
    private final Color suggestionFocusedColor;

    public AutoSuggestor(JTextField textField, Window mainWindow, ArrayList words, Color popUpBackground, Color textColor, Color suggestionFocusedColor, float opacity) 
        this.textField = textField;
        this.suggestionsTextColor = textColor;
        this.container = mainWindow;
        this.suggestionFocusedColor = suggestionFocusedColor;
        this.textField.getDocument().addDocumentListener(documentListener);

        setDictionary(words);

        typedWord = "";
        currentIndexOfSpace = 0;
        tW = 0;
        tH = 0;

        autoSuggestionPopUpWindow = new JWindow(mainWindow);
        autoSuggestionPopUpWindow.setOpacity(opacity);

        suggestionsPanel = new JPanel();
        suggestionsPanel.setLayout(new GridLayout(0, 1));
        suggestionsPanel.setBackground(popUpBackground);

        addKeyBindingToRequestFocusInPopUpWindow();
    

    private void addKeyBindingToRequestFocusInPopUpWindow() 
        textField.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Down released");
        textField.getActionMap().put("Down released", new AbstractAction() 
            @Override
            public void actionPerformed(ActionEvent ae) //focuses the first label on popwindow
                for (int i = 0; i < suggestionsPanel.getComponentCount(); i++) 
                    if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) 
                        ((SuggestionLabel) suggestionsPanel.getComponent(i)).setFocused(true);
                        autoSuggestionPopUpWindow.toFront();
                        autoSuggestionPopUpWindow.requestFocusInWindow();
                        suggestionsPanel.requestFocusInWindow();
                        suggestionsPanel.getComponent(i).requestFocusInWindow();
                        break;
                    
                
            
        );
        suggestionsPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Down released");
        suggestionsPanel.getActionMap().put("Down released", new AbstractAction() 
            int lastFocusableIndex = 0;

            @Override
            public void actionPerformed(ActionEvent ae) //allows scrolling of labels in pop window (I know very hacky for now :))

                ArrayList sls = getAddedSuggestionLabels();
                int max = sls.size();

                if (max > 1) //more than 1 suggestion
                    for (int i = 0; i < max; i++) 
                        SuggestionLabel sl = sls.get(i);
                        if (sl.isFocused()) 
                            if (lastFocusableIndex == max - 1) 
                                lastFocusableIndex = 0;
                                sl.setFocused(false);
                                autoSuggestionPopUpWindow.setVisible(false);
                                setFocusToTextField();
                                checkForAndShowSuggestions();//fire method as if document listener change occured and fired it

                             else 
                                sl.setFocused(false);
                                lastFocusableIndex = i;
                            
                         else if (lastFocusableIndex <= i) 
                            if (i < max) 
                                sl.setFocused(true);
                                autoSuggestionPopUpWindow.toFront();
                                autoSuggestionPopUpWindow.requestFocusInWindow();
                                suggestionsPanel.requestFocusInWindow();
                                suggestionsPanel.getComponent(i).requestFocusInWindow();
                                lastFocusableIndex = i;
                                break;
                            
                        
                    
                 else //only a single suggestion was given
                    autoSuggestionPopUpWindow.setVisible(false);
                    setFocusToTextField();
                    checkForAndShowSuggestions();//fire method as if document listener change occured and fired it
                
            
        );
    

    private void setFocusToTextField() 
        container.toFront();
        container.requestFocusInWindow();
        textField.requestFocusInWindow();
    

    public ArrayList getAddedSuggestionLabels() 
        ArrayList sls = new ArrayList<>();
        for (int i = 0; i < suggestionsPanel.getComponentCount(); i++) 
            if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) 
                SuggestionLabel sl = (SuggestionLabel) suggestionsPanel.getComponent(i);
                sls.add(sl);
            
        
        return sls;
    

    private void checkForAndShowSuggestions() 
        typedWord = getCurrentlyTypedWord();

        suggestionsPanel.removeAll();//remove previos words/jlabels that were added

        //used to calcualte size of JWindow as new Jlabels are added
        tW = 0;
        tH = 0;

        boolean added = wordTyped(typedWord);

        if (!added) 
            if (autoSuggestionPopUpWindow.isVisible()) 
                autoSuggestionPopUpWindow.setVisible(false);
            
         else 
            showPopUpWindow();
            setFocusToTextField();
        
    

    protected void addWordToSuggestions(String word) 
        SuggestionLabel suggestionLabel = new SuggestionLabel(word, suggestionFocusedColor, suggestionsTextColor, this);

        calculatePopUpWindowSize(suggestionLabel);

        suggestionsPanel.add(suggestionLabel);
    

    public String getCurrentlyTypedWord() //get newest word after last white spaceif any or the first word if no white spaces
        String text = textField.getText();
        String wordBeingTyped = "";
        if (text.contains(" ")) 
            int tmp = text.lastIndexOf(" ");
            if (tmp >= currentIndexOfSpace) 
                currentIndexOfSpace = tmp;
                wordBeingTyped = text.substring(text.lastIndexOf(" "));
            
         else 
            wordBeingTyped = text;
        
        return wordBeingTyped.trim();
    

    private void calculatePopUpWindowSize(JLabel label) 
        //so we can size the JWindow correctly
        if (tW < label.getPreferredSize().width) 
            tW = label.getPreferredSize().width;
        
        tH += label.getPreferredSize().height;
    

    private void showPopUpWindow() 
        autoSuggestionPopUpWindow.getContentPane().add(suggestionsPanel);
        autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textField.getWidth(), 30));
        autoSuggestionPopUpWindow.setSize(tW, tH);
        autoSuggestionPopUpWindow.setVisible(true);

        int windowX = 0;
        int windowY = 0;

        windowX = container.getX() + textField.getX() + 5;
        if (suggestionsPanel.getHeight() > autoSuggestionPopUpWindow.getMinimumSize().height) 
            windowY = container.getY() + textField.getY() + textField.getHeight() + autoSuggestionPopUpWindow.getMinimumSize().height;
         else 
            windowY = container.getY() + textField.getY() + textField.getHeight() + autoSuggestionPopUpWindow.getHeight();
        

        autoSuggestionPopUpWindow.setLocation(windowX, windowY);
        autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textField.getWidth(), 30));
        autoSuggestionPopUpWindow.revalidate();
        autoSuggestionPopUpWindow.repaint();

    

    public void setDictionary(ArrayList words) 
        dictionary.clear();
        if (words == null) 
            return;//so we can call constructor with null value for dictionary without exception thrown
        
        for (String word : words) 
            dictionary.add(word);
        
    

    public JWindow getAutoSuggestionPopUpWindow() 
        return autoSuggestionPopUpWindow;
    

    public Window getContainer() 
        return container;
    

    public JTextField getTextField() 
        return textField;
    

    public void addToDictionary(String word) 
        dictionary.add(word);
    

    boolean wordTyped(String typedWord) 

        if (typedWord.isEmpty()) 
            return false;
        
        //System.out.println("Typed word: " + typedWord);

        boolean suggestionAdded = false;

        for (String word : dictionary) //get words in the dictionary which we added
            boolean fullymatches = true;
            for (int i = 0; i < typedWord.length(); i++) //each string in the word
                if (!typedWord.toLowerCase().startsWith(String.valueOf(word.toLowerCase().charAt(i)), i)) //check for match
                    fullymatches = false;
                    break;
                
            
            if (fullymatches) 
                addWordToSuggestions(word);
                suggestionAdded = true;
            
        
        return suggestionAdded;
    


class SuggestionLabel extends JLabel 

    private boolean focused = false;
    private final JWindow autoSuggestionsPopUpWindow;
    private final JTextField textField;
    private final AutoSuggestor autoSuggestor;
    private Color suggestionsTextColor, suggestionBorderColor;

    public SuggestionLabel(String string, final Color borderColor, Color suggestionsTextColor, AutoSuggestor autoSuggestor) 
        super(string);

        this.suggestionsTextColor = suggestionsTextColor;
        this.autoSuggestor = autoSuggestor;
        this.textField = autoSuggestor.getTextField();
        this.suggestionBorderColor = borderColor;
        this.autoSuggestionsPopUpWindow = autoSuggestor.getAutoSuggestionPopUpWindow();

        initComponent();
    

    private void initComponent() 
        setFocusable(true);
        setForeground(suggestionsTextColor);

        addMouseListener(new MouseAdapter() 
            @Override
            public void mouseClicked(MouseEvent me) 
                super.mouseClicked(me);

                replaceWithSuggestedText();

                autoSuggestionsPopUpWindow.setVisible(false);
            
        );

        getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "Enter released");
        getActionMap().put("Enter released", new AbstractAction() 
            @Override
            public void actionPerformed(ActionEvent ae) 
                replaceWithSuggestedText();
                autoSuggestionsPopUpWindow.setVisible(false);
            
        );
    

    public void setFocused(boolean focused) 
        if (focused) 
            setBorder(new LineBorder(suggestionBorderColor));
         else 
            setBorder(null);
        
        repaint();
        this.focused = focused;
    

    public boolean isFocused() 
        return focused;
    

    private void replaceWithSuggestedText() 
        String suggestedWord = getText();
        String text = textField.getText();
        String typedWord = autoSuggestor.getCurrentlyTypedWord();
        String t = text.substring(0, text.lastIndexOf(typedWord));
        String tmp = t + text.substring(text.lastIndexOf(typedWord)).replace(typedWord, suggestedWord);
        textField.setText(tmp + " ");
    

Tal como está, las únicas posibles adiciones necesarias en mi opinión son:

  • HASTA key Enfoque la transversabilidad de los elementos dentro del cuadro emergente de sugerencias automáticas para que podamos ir en una dirección ascendente.

Si hay algún problema, déjame saber que veré qué puedo hacer. Pero parece funcionar bien (toque madera).

Una forma realmente sencilla de hacerlo es utilizar el GlazedList implementación de autocompletado. Es muy fácil de poner en marcha. Lo puedes encontrar aquí.

Puede instalar el autocompletar en un JComboBox con solo una línea de código Glazed, como este:

JComboBox comboBox = new JComboBox();
Object[] elements = new Object[] "Cat", "Dog", "Lion", "Mouse";
AutoCompleteSupport.install(comboBox, GlazedLists.eventListOf(elements));

También SwingX admite autocompletar y puede ser más fácil de usar que GlazedList. Todo lo que escribes con SwingX es AutoCompleteDecorator.decorate(comboBox);

Para usar la clase TextAutoCompleter, debe descargar un archivo jar AutoCompleter.jar y agregarlo a la carpeta de la biblioteca de su proyecto y aquí está el enlace para descargar: http://download1689.mediafire.com/4grrthscpsug/7pwzgefiomu392o/AutoCompleter.jar -Nawin

// En la clase Main escribe el siguiente código

package autocomplete;

import com.mxrck.autocompleter.TextAutoCompleter;
import java.sql.SQLException;
import javax.swing.JFrame;
import javax.swing.JTextField;


public class AutoComplete 
    JFrame f=new JFrame();
    JTextField t1;
AutoComplete() throws ClassNotFoundException, SQLException

    f.setSize(500,500);
    f.setLocation(500,100);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLayout(null);
    f.setVisible(true);


    t1=new JTextField();
    t1.setBounds(50,80,200,20);
    f.add(t1);


    TextAutoCompleter complete=new TextAutoCompleter(t1);
    DBConn conn=new DBConn();
        conn.connection();
        conn.retrieve();
    while(conn.rs.next())

        complete.addItem(conn.rs.getString("number"));
    





    public static void main(String[] args) throws ClassNotFoundException,
    SQLException           

        new AutoComplete();
   




//Create seperate class for database connection and write the following code


package autocomplete;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class DBConn 

    Connection con; ResultSet rs;PreparedStatement stat;

public void connection() throws ClassNotFoundException, SQLException
    String url="jdbc:mysql://localhost:3306/";
    String driver="com.mysql.jdbc.Driver";   
    String db="demo";
    String username="root";
    String password="root";
    stat =null; 

        Class.forName(driver);
       con=(Connection)DriverManager.getConnection
       (url+db,username,password);              
        System.out.println("Connecttion SuccessFul");
  

public void retrieve() throws SQLException

    Statement  stmt=con.createStatement();
    String query="select number from phone";
    rs = stmt.executeQuery(query);

    System.out.println("retrieve succesfully");


Tienes la opción de animar nuestra misión ejecutando un comentario y puntuándolo te lo agradecemos.

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


Tags :

Utiliza Nuestro Buscador

Deja una respuesta

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