-1

I want to perform auto-completion of jtextfield, for this purpose i google it and found some good examples and code snippets, but my scenario is different from all these, normally every example auto-complete the field, for example say, if i press S it will auto-complete with Stackoverflow or if i press G it will complete google etc, means its need only first character for auto-completion.

But my problem is this, i want to perform auto-completion when first 4 characters will typed or entered say if i typed stac than it should be auto-complete it to stackoverflow, not with first character S.

Please guide me how will i do this i'm stuck badly on this problem.

following code i use for my working class

package testautocomp;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;

public class JTextFieldAutoCompletion extends JTextField implements DocumentListener, ActionListener{

    /**
     * 
     */
    private static final long serialVersionUID = 4810213451949301347L;

    //Les Données De L'AutoCompletion
    private List<String> data = new ArrayList<String>();

    //Un Constructeur Par Défaut
    public JTextFieldAutoCompletion() {
        //Par Defaut Le Nombre de caractère visible dans le champs de texte est 25
        this(25);
    }
    /**
     * Un Constructeur Paramétré
     * @param columns nombre de caractère visible dans le champs de texte
     */
    public JTextFieldAutoCompletion(int columns) {
        //passer au constructeur à deux arguments le nombre de colonne visible dans le champs de texte et definir les données de l'autocompletion à null.
        this(columns, null);
    }
    /**
     * Constructeur Paramétré à deux arguments
     * @param columns nombre de caractère visible dans le champs de texte
     * @param data les données de l'autocompletion
     */
    public JTextFieldAutoCompletion(int columns, List<String> data) {
        super(columns);
        //ici on fait appel à la méthode setDataCompletion pour definir les données de l'autocompletion
        this.setDataCompletion(data);
        //je défini l'ecouteur de l'evenement de la saisie
        this.getDocument().addDocumentListener(this);
        //je défini j'ecouteur de la touche entrer
        this.addActionListener(this);
    }
    /**
     * Permet De Redefinir les données de l'autocompletion
     * @param data les données de l'autocompletion
     */
    public void setDataCompletion(List<String> data) {
        //on affecte seulement si data est déffirent à null
        if(data != null)
            this.data = data;
        //on va trier les données de l'autocompletion 
        Collections.sort(this.data);
    }
    /**
     * Evenement Déclenché à chaque fois que l'utilisateur tape un caractère quelconque, ou fasse une copier/coller dans le champs de texte.
     */
    @Override
    public void insertUpdate(DocumentEvent e) {
        // TODO Stub de la méthode généré automatiquement
        //on arréte l'exécution de l'evenement si l'utilisateur fasse une copier/coller
        if(e.getLength() != 1) return;

        //on récupére la position du dernier caratère saisie en comptant de zéro, premier caractère est en position 0, le deuxième à 2 etc..
        int pos = e.getOffset();
        String prefix = null;
        try {
            //on recupére dans prefix ce qu'a saisi l'utilisateur jusqu'à présent.
            prefix = this.getText(0, pos + 1);
        } catch (BadLocationException e1) {}

        //on fait une recherche sur la chaine qu'a saisi l'utilisateur dans les données de l'autocompletion. 
        //la méthode binarySearch retourne :
        //Soit l'index de l'element cherché s'il est contenu dans la collection.
        //Soit le nombre d'element de la collection si tous les elements sont inférieurs à l'element qu'on cherche.
        //Soit un entier négatif qui représente l'index de premier element supérieur de l'element qu'on cherche.
        int index = Collections.binarySearch(data, prefix);

        if(index < 0 && -index <= data.size()) {
            //Completion Trouvé
            //On récupére le premier element supérieur à l'element cherché. le signe - retourne la valeur absolue de la variable index. 
            String match = data.get(-index - 1);

            //on s'assure que la chaine dans la variable match commence par la chaine contenu dans la variable prefix c-à-d ce qu'a saisi l'utilisateur 
            if(match.startsWith(prefix)) {
                //si oui on met on place l'autocompletion sinon on fait rien :).
                SwingUtilities.invokeLater(new AutoCompletion(pos, match));
            }
        } else ;
            //Aucune Completion Trouvé

    }
    /**
     * Permet De Valider L'AutoCompletion En Cliquant Sur La Touche Entrer
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Stub de la méthode généré automatiquement
        setCaretPosition(getSelectionEnd());
    }
    @Override
    public void removeUpdate(DocumentEvent e) {}
    @Override
    public void changedUpdate(DocumentEvent e) {}

    private class AutoCompletion implements Runnable{
        private int pos;
        private String completion;

        public AutoCompletion(int pos, String completion) {
            this.pos = pos;
            this.completion = completion;
        }
        @Override
        public void run() {
            // TODO Stub de la méthode généré automatiquement
            //On affecte la chaine trouvé pour l'autocompletion dans le champs de texte
            setText(completion);
            //on definit à partir d'où va débuter la séléction des caractères ajouté comme completion. 
            //j'ai précisé qu'il va débuter de la fin vers le dernier caractère sasie par l'utilisateur
            setCaretPosition(completion.length());
            //j'ai appliqué la séléction jusqu'au dernier caractère sasie par l'utilisateur
            moveCaretPosition(pos + 1);
        }       
    }
}

and here is my main class

package testautocomp;

import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

public class TestAutoComp {
    public static void main(String[] a) {
        JFrame f = new JFrame();
        JTextFieldAutoCompletion tf = new JTextFieldAutoCompletion(25);

        List<String> data = new ArrayList<String>();
        data.add("jtextfield autocompletion");
        data.add("java swing");
        data.add("je veux apprendre java");
        data.add("stackoverflow");
        data.add("ahad");       


        tf.setDataCompletion(data);
        f.getContentPane().add(tf, "North");

        f.pack();f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
        f.setLocationRelativeTo(null); 
        f.setVisible(true);
    } 
}
ahad
  • 37
  • 1
  • 2
  • 8
  • (1-) `i google it and found some good examples` - so then modify the examples to meet your requirements. You can easily check the number of characters currently entered in the text field. – camickr Jun 14 '16 at 20:56
  • @(1-) i post my code above, kindly will you help me in this. – ahad Jun 14 '16 at 21:16
  • I did give help. You check the length of the text in the text field. If the length is what you want you do your processing otherwise you just exit the method. – camickr Jun 15 '16 at 00:44

1 Answers1

0

According to your question you wish to perform auto-completion when first 4 characters will typed,Then just give check in your insertUpdate() method, that length of the text in the text field is greater than 3,so will get expected output. I have modified your code for expected result.

 package temp;
 import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;

public class JTextFieldAutoCompletion extends JTextField implements DocumentListener, ActionListener{

/**
 * 
 */
private static final long serialVersionUID = 4810213451949301347L;

//Les Données De L'AutoCompletion
private List<String> data = new ArrayList<String>();

//Un Constructeur Par Défaut
public JTextFieldAutoCompletion() {
    //Par Defaut Le Nombre de caractère visible dans le champs de texte est 25
    this(25);
}
/**
 * Un Constructeur Paramétré
 * @param columns nombre de caractère visible dans le champs de texte
 */
public JTextFieldAutoCompletion(int columns) {
    //passer au constructeur à deux arguments le nombre de colonne visible dans le champs de texte et definir les données de l'autocompletion à null.
    this(columns, null);
}
/**
 * Constructeur Paramétré à deux arguments
 * @param columns nombre de caractère visible dans le champs de texte
 * @param data les données de l'autocompletion
 */
public JTextFieldAutoCompletion(int columns, List<String> data) {
    super(columns);
    //ici on fait appel à la méthode setDataCompletion pour definir les données de l'autocompletion
    this.setDataCompletion(data);
    //je défini l'ecouteur de l'evenement de la saisie
    this.getDocument().addDocumentListener(this);
    //je défini j'ecouteur de la touche entrer
    this.addActionListener(this);
}
/**
 * Permet De Redefinir les données de l'autocompletion
 * @param data les données de l'autocompletion
 */
public void setDataCompletion(List<String> data) {
    //on affecte seulement si data est déffirent à null
    if(data != null)
        this.data = data;
    //on va trier les données de l'autocompletion 
    Collections.sort(this.data);
}
/**
 * Evenement Déclenché à chaque fois que l'utilisateur tape un caractère quelconque, ou fasse une copier/coller dans le champs de texte.
 */
@Override
public void insertUpdate(DocumentEvent e) {
    // TODO Stub de la méthode généré automatiquement
    //on arréte l'exécution de l'evenement si l'utilisateur fasse une copier/coller

    if(this.getText().length()>3){
    if(e.getLength() != 1) return;

    //on récupére la position du dernier caratère saisie en comptant de zéro, premier caractère est en position 0, le deuxième à 2 etc..
    int pos = e.getOffset();
    String prefix = null;
    try {
        //on recupére dans prefix ce qu'a saisi l'utilisateur jusqu'à présent.
        prefix = this.getText(0, pos + 1);
    } catch (BadLocationException e1) {}

    //on fait une recherche sur la chaine qu'a saisi l'utilisateur dans les données de l'autocompletion. 
    //la méthode binarySearch retourne :
    //Soit l'index de l'element cherché s'il est contenu dans la collection.
    //Soit le nombre d'element de la collection si tous les elements sont inférieurs à l'element qu'on cherche.
    //Soit un entier négatif qui représente l'index de premier element supérieur de l'element qu'on cherche.
    int index = Collections.binarySearch(data, prefix);

    if(index < 0 && -index <= data.size()) {
        //Completion Trouvé
        //On récupére le premier element supérieur à l'element cherché. le signe - retourne la valeur absolue de la variable index. 
        String match = data.get(-index - 1);

        //on s'assure que la chaine dans la variable match commence par la chaine contenu dans la variable prefix c-à-d ce qu'a saisi l'utilisateur 
        if(match.startsWith(prefix)) {
            //si oui on met on place l'autocompletion sinon on fait rien :).
            SwingUtilities.invokeLater(new AutoCompletion(pos, match));
        }
    } else ;
        //Aucune Completion Trouvé
    }
}
/**
 * Permet De Valider L'AutoCompletion En Cliquant Sur La Touche Entrer
 */
@Override
public void actionPerformed(ActionEvent e) {
    // TODO Stub de la méthode généré automatiquement
    setCaretPosition(getSelectionEnd());
}
@Override
public void removeUpdate(DocumentEvent e) {}
@Override
public void changedUpdate(DocumentEvent e) {}

private class AutoCompletion implements Runnable{
    private int pos;
    private String completion;

    public AutoCompletion(int pos, String completion) {
        this.pos = pos;
        this.completion = completion;
    }
    @Override
    public void run() {
        // TODO Stub de la méthode généré automatiquement
        //On affecte la chaine trouvé pour l'autocompletion dans le champs de texte
        setText(completion);
        //on definit à partir d'où va débuter la séléction des caractères ajouté comme completion. 
        //j'ai précisé qu'il va débuter de la fin vers le dernier caractère sasie par l'utilisateur
        setCaretPosition(completion.length());
        //j'ai appliqué la séléction jusqu'au dernier caractère sasie par l'utilisateur
        moveCaretPosition(pos + 1);
    }       
}

}

Shree
  • 787
  • 8
  • 23