Implementing auto complete in Java - am I doing it right?

An SO User picture An SO User · Feb 13, 2013 · Viewed 22.2k times · Source

Algorithm

  1. Start
  2. Input a city name - partial or complete
  3. If the user hits enter , take the text from JTextField
  4. Begin brute force search.
  5. If the matches are found, put them in a Vector and put it in a JList
  6. If no match is found, add a String "No Match Found" in Vector
  7. Display JWindow to user containing the results
  8. Stop

Code:

package test;
import javax.swing.*;

import java.awt.Dimension;
import java.awt.event.*;
import java.util.Vector;

public class AutoCompleteTest extends JFrame{
    JTextField city = new JTextField(10);
    String enteredName = null;
    String[] cities = {"new jersey","new hampshire",
            "sussex","essex","london","delhi","new york"};
    JList list = new JList();
    JScrollPane pane = new JScrollPane();
    ResultWindow r = new ResultWindow();
//------------------------------------------------------------------------------
    public static void main(String[] args) {
        new AutoCompleteTest();
    }
//------------------------------------------------------------------------------
    public AutoCompleteTest(){
        setLayout(new java.awt.FlowLayout());
        setVisible(true);
        add(city);
//      add(pane);
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        city.addKeyListener(new TextHandler());
    }
//------------------------------------------------------------------------------
    public void initiateSearch(String lookFor){
        Vector<String> matches = new Vector<>();
        lookFor = lookFor.toLowerCase();
        for(String each : cities){
            if(each.contains(lookFor)){
                matches.add(each);
                System.out.println("Match: " + each);
            }
        }
        this.repaint();

        if(matches.size()!=0){
            list.setListData(matches);
            r.searchResult = list;
            r.pane = pane;
            r.initiateDisplay();
        }else{
            matches.add("No Match Found");
            list.setListData(matches);
            r.searchResult = list;
            r.pane = pane;
            r.initiateDisplay();
        }

    }
//------------------------------------------------------------------------------
    public class ResultWindow extends JWindow{
        public JScrollPane pane;
        public JList searchResult;
//------------------------------------------------------------------------------
        public ResultWindow(){

        }
//------------------------------------------------------------------------------
        public void initiateDisplay(){
            pane.setViewportView(searchResult);
            add(pane);
            pack();
            this.setLocation(AutoCompleteTest.this.getX() + 2, 
                    AutoCompleteTest.this.getY()+
                    AutoCompleteTest.this.getHeight());

//          this.setPreferredSize(city.getPreferredSize());
            this.setVisible(true);
        }
    }
//------------------------------------------------------------------------------

    class TextHandler implements KeyListener{
        @Override
        public void keyTyped(KeyEvent e){

        }

        @Override
        public void keyPressed(KeyEvent e){
            if(r.isVisible()){
                r.setVisible(false);
            }
            if(e.getKeyChar() == '\n'){
                initiateSearch(city.getText());
            }
        }

        @Override
        public void keyReleased(KeyEvent e){

        }
    }
//------------------------------------------------------------------------------
}

Output

enter image description here

Problem

The size of the JWindow displaying the results (which is a JList in a JScrollPane) changes based on the results - if the city name is small, JWindow is small, if the city name is big, JWindow is big.

I have tried every possible combination. I tried using setPreferredDimension() of the JWindow, the JList and JScrollPane but the issue won't go.
I want it to match the size of the decorated JFrame no matter what

Answer

mKorbel picture mKorbel · Feb 13, 2013

EDIT

Anyways so basically I will have to manually create a list of all the cities that are to be supported right ?? bx @Little Child

  • this idea could be quite easy, you can to put JTable to the JWindow

  • with one Column,

  • without JTableHeader

  • add there RowSorter (see code example in tutorial)

  • then every steps are done :-), nothing else is required there (maybe bonus to change Background of JTextField in the case that RowFilter returns no matches, add setVisible for popup window from DocumentListener (be sure to test for !isVisible))