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)
