Creating an Autocomplete Text Field in Java using SwingX

Again, my friend Iswi asked me a simple question, but a little bit hard to do. She asked me, how can she create an autocomplete jtextfield in java, maybe something like NetBean’s autocompletion feature. It took me a while to try several workarounds, before i found a very neat library, swingx. Let just say that this SwingX library helped me alot, and it have lots of other cool swing components. Really worth a try.

In this example, i try to create a simple application consist of 2 autocompletion components, 1 unrestricted jcombobox and 1 restricted jtextfield. Both components will connect to one table using Hibernate. Let’s give it a try.

First, a simple 2 column table.

CREATE DATABASE 'test'
USE 'test'

CREATE TABLE 'contoh' (
  'nama' varchar(30) NOT NULL,
  'alamat' varchar(100) DEFAULT NULL,
  PRIMARY KEY ('nama')
) 

next step is creating a java bean and its hbm.xml for database mapping

package com.edw.bean;

/**
 * Contoh generated by hbm2java
 */
public class Contoh implements java.io.Serializable {

    private String nama;
    private String alamat;

    public Contoh() {
    }

    public Contoh(String nama) {
        this.nama = nama;
    }

    public Contoh(String nama, String alamat) {
        this.nama = nama;
        this.alamat = alamat;
    }

    public String getNama() {
        return this.nama;
    }

    public void setNama(String nama) {
        this.nama = nama;
    }

    public String getAlamat() {
        return this.alamat;
    }

    public void setAlamat(String alamat) {
        this.alamat = alamat;
    }
}

FYI, im using NetBeans’ Hibernate POJO and XML generator.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 1, 2010 10:10:38 AM by Hibernate Tools 3.2.1.GA -->
<hibernate-mapping>
  <class catalog="test" name="com.edw.bean.Contoh" table="contoh">
    <id name="nama" type="string">
      <column length="30" name="nama"/>
      <generator class="assigned"/>
    </id>
    <property name="alamat" type="string">
      <column length="100" name="alamat"/>
    </property>
  </class>
</hibernate-mapping>

this is my hibernate.cfg.xml, for my default hibernate configuration

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
    <property name="hibernate.connection.username">admin</property>
    <property name="hibernate.connection.password">xxx</property>
    <mapping resource="com/edw/bean/Contoh.hbm.xml"/>
  </session-factory>
</hibernate-configuration>

and my java class to load hibernate’s main xml configuration

package com.edw.hbm.util;

import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;

/**
 * Hibernate Utility class with a convenient method to get Session Factory object.
 *
 * @author edw
 */
public class HibernateUtil {
    private static final SessionFactory sessionFactory;

    static {
        try {
            // Create the SessionFactory from standard (hibernate.cfg.xml) 
            // config file.
            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Log the exception. 
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

this is my main java class, you’ll see some imported SwingX’s classes.

package com.edw.swingx;

import com.edw.bean.Contoh;
import com.edw.hbm.util.HibernateUtil;
import java.awt.Container;
import java.awt.FlowLayout;
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.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTextField;
import org.apache.log4j.Logger;
import org.hibernate.Session;

import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator;
import org.jdesktop.swingx.combobox.ListComboBoxModel;

/**
 *
 * @author edw
 */
public class AutoCompletionTextField extends JFrame implements ActionListener {

    private JButton button = new JButton("tombol");
    private JComboBox comboComplete = new JComboBox();
    private JTextField textComplete = new JTextField(30);
    private Logger logger = Logger.getLogger(this.getClass());
    private List<String> strings = new ArrayList<String>();

    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button){
            logger.debug(comboComplete.getSelectedItem().toString());
            logger.debug(textComplete.getText().toString());
        }
    }

    public AutoCompletionTextField() {

        try {
            Session session = HibernateUtil.getSessionFactory().openSession();
            List<Contoh> contohs = (List<Contoh>)session.createCriteria(Contoh.class).list();
            session.close();

            for (Contoh contoh : contohs) {
                strings.add(contoh.getNama());
            }

            Collections.sort(strings);

            // change true to false to enable string restriction
            comboComplete.setEditable(true);
            comboComplete.setModel(new ListComboBoxModel<String>(strings));

            AutoCompleteDecorator.decorate(comboComplete);
            // change true to false to disable string restriction
            AutoCompleteDecorator.decorate(textComplete, strings, true);

            Container con = getContentPane();
            con.setLayout(new FlowLayout());
            con.add(comboComplete);
            con.add(textComplete);
            con.add(button);

            button.addActionListener(this);
            comboComplete.addActionListener(this);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
    }
    
    public static void main(String[] args) {
        AutoCompletionTextField autoCompletionTextField = new AutoCompletionTextField();
        autoCompletionTextField.setVisible(true);
        autoCompletionTextField.pack();
        autoCompletionTextField.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

this is my UI result,

this is NetBeans 6.9 project structure,

Again, thank you Iswi for your questions. Cheers, (B)

9 thoughts on “Creating an Autocomplete Text Field in Java using SwingX”

  1. may i have your demo? i don’t understand how it works. there is so many new thing that i never know before. but after all, thanks you have share this information.

    1. Hi Yuda,
      you can just copy paste my sourcecode from my blog, it’s the same sourcecode i have on my IDE. 🙂

  2. Hello Edwin thanks for the Example provided above. I have used same code, but now i’m getting error in AutoCompletionTextField.java file at the line number 31 ( private Logger logger = Logger.getLogger(this.getClass()); ) Please help me that did i miss any jar files. Thanks in advance.

  3. Hello Edwin, thank you very much. The example is fantastic to beginners. And I have an requirement of code. Could you please help me. If so I’ll mail you the requirement. Thank you again

    1. Hi Abhinandan,
      its been a while since the last time ive create a jtable component, but if i recall you need to implements cellrenderer, a little bit tricky actually 😀

  4. maaf saya sudah mencoba semua kode java yang anda buat beserta semua jar seperti yang ada di punya anda, tapi setelah saya compile tetap saja error. Bolehkah saya minta code mentahan anda. kirim ke email saya morgan_ptr@yahoo.com. Terima Kasih.

    Ini pesan errornya :
    Initial SessionFactory creation failed.java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
    Exception in thread “main” java.lang.ExceptionInInitializerError
    at com.edw.hbm.util.HibernateUtil.(HibernateUtil.java:22)
    at com.edw.swingx.AutoCompletionTextField.(AutoCompletionTextField.java:44)
    at com.edw.swingx.AutoCompletionTextField.main(AutoCompletionTextField.java:76)
    Caused by: java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
    at org.hibernate.cfg.Configuration.(Configuration.java:197)
    at com.edw.hbm.util.HibernateUtil.(HibernateUtil.java:18)
    … 2 more
    Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    … 4 more

Leave a Reply to Abhinandan Cancel Reply

Your email address will not be published.