basic Posts

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)

Calling a JInternalFrame from a JDialog

Yesterday, my friend Iswi asked me a question, how can she called a JinternalFrame from a JDialog, and put it in an existing JDesktopPane? Well Iswi, here are your answers.

First i create a very simple JFrame application

package com.edw.ui;

import java.awt.BorderLayout;
import java.awt.Container;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import org.apache.log4j.Logger;

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

    private JDesktopPane desktopPane = new JDesktopPane();
    private JMenuBar jMenuBar = new JMenuBar();
    private JMenu menuTest = new JMenu("Test");
    private JMenuItem jMenuItem = new JMenuItem("execute");
    private Logger logger = Logger.getLogger(this.getClass());

    public FrameMain() {
        Container con = getContentPane();  
        con.setLayout(new BorderLayout());
        con.add(desktopPane, BorderLayout.CENTER);

        menuTest.add(jMenuItem);
        jMenuBar.add(menuTest);

        setJMenuBar(jMenuBar);

        jMenuItem.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == jMenuItem) {
            logger.debug("in jmenuitem");
            InternalTestOne internalTestSatu = new InternalTestOne(this);
            internalTestSatu.setVisible(true);
            getDesktopPane().add(internalTestSatu);
        }
    }

    public static void main(String[] args) {
        FrameMain frameMain = new FrameMain();
        frameMain.setVisible(true);
        frameMain.setLocationRelativeTo(null);        
        frameMain.setSize(800, 500);
        frameMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frameMain.setTitle("bubu");
    }

    public JDesktopPane getDesktopPane() {
        return desktopPane;
    }

    public void setDesktopPane(JDesktopPane desktopPane) {
        this.desktopPane = desktopPane;
    }
}

and this is my first JInternalFrame, it will call a JDialog class,

package com.edw.ui;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;

import javax.swing.JInternalFrame;
import org.apache.log4j.Logger;

/**
 *
 * @author edw
 */
public class InternalTestOne extends JInternalFrame implements ActionListener {

    private Logger logger = Logger.getLogger(this.getClass());
    private JButton button = new JButton("Klik Dialog");
    private FrameMain frameMain = new FrameMain();

    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button){
            logger.debug("in ActionPerformed InternalTestSatu");

            // show jdialog
            DialogTest dialogTest = new DialogTest(frameMain);
            dialogTest.setVisible(true);
        }
    }

    public InternalTestOne(FrameMain frameMain) {
        super("internal satu", true, true, true, true);
        this.frameMain = frameMain;
        setSize(300,300);
        logger.debug("in InternalTestSatu");

        Container con = getContentPane();
        con.setLayout(new FlowLayout());
        con.add(button);
        button.addActionListener(this);
    }

}

and this is my JDialog class

package com.edw.ui;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;

import org.apache.log4j.Logger;

/**
 *
 * @author edw
 */
public class DialogTest extends JDialog implements ActionListener {

    private JButton button = new JButton("call Internal Frame");
    private Logger logger = Logger.getLogger(this.getClass());
    private FrameMain frameMain = new FrameMain();

    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button){
            logger.debug("at actionPerformed "+this.getClass().getName());

            // call jinternalframe from here           
            InternalTestTwo internalTestTwo = new InternalTestTwo();
            internalTestTwo.setVisible(true);
            frameMain.getDesktopPane().add(internalTestTwo);
            this.setVisible(false);
            this.dispose();
        }
    }

    public DialogTest(FrameMain frameMain) {
        super(frameMain);
        this.frameMain = frameMain;
        setTitle("Calling JInternalFrame");
        Container con = getContentPane();
        con.setLayout(new FlowLayout());
        con.add(button);
        setLocationRelativeTo(null);
        setSize(300,200);
        pack();
        button.addActionListener(this);
    }

}

and finally, this is my second JInternalFrame , it will be called from a JDialog

package com.edw.ui;

import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import org.apache.log4j.Logger;

/**
 *
 * @author edw
 */
public class InternalTestTwo extends JInternalFrame {

    private JLabel label = new JLabel("Called from JDialog");
    private Logger logger = Logger.getLogger(this.getClass());

    public InternalTestTwo() {
        super("internal Two Called from JDialog", true, true, true, true);
        setSize(300, 300);
        setLocation(100,200);
        logger.debug("constructor of "+this.getClass().getName());

        Container con = getContentPane();
        con.setLayout(new FlowLayout());
        con.add(label);
    }
}

and this is how my simple app looks like,

Thanks for your questions, Iswi. Always remember, stay hungry, stay foolish.
:-[

Random Date Generator dengan Java

Iseng-iseng bikin class sederhana untuk menghasilkan suatu tanggal random yang terletak antara tanggalSebelum (Date) dan tanggalSesudah (Date). Rencananya ini mo gw pakek bwt testing aplikasi. Sorry klo classnya rada berantakan, bikinnya juga buru-buru, sembari nunggu adzan Maghrib.

package com.edw.random;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 
 * @author edwin
 */
public class RandomDateGenerator extends Thread {

	private Date sebelum;
	private Date sesudah;
	private int repetition;

	public Date getSebelum() {
		return sebelum;
	}

	public void setSebelum(Date sebelum) {
		this.sebelum = sebelum;
	}

	public Date getSesudah() {
		return sesudah;
	}

	public void setSesudah(Date sesudah) {
		this.sesudah = sesudah;
	}

	public int getRepetition() {
		return repetition;
	}

	public void setRepetition(int repetition) {
		this.repetition = repetition;
	}

	public RandomDateGenerator() {
	}

	@Override
	public void run() {
		try {
			for (int i = 0; i < repetition; i++) {
				Thread.sleep(1000);
				System.out.println(getRandomDateBetween(sebelum, sesudah));
			}
		} catch (InterruptedException interruptedException) {
			interruptedException.printStackTrace();
		}
	}

	private synchronized Date getRandomDateBetween(Date from, Date to) {
		Calendar cal = Calendar.getInstance();

		cal.setTime(from);
		BigDecimal decFrom = new BigDecimal(cal.getTimeInMillis());

		cal.setTime(to);
		BigDecimal decTo = new BigDecimal(cal.getTimeInMillis());

		BigDecimal selisih = decTo.subtract(decFrom);
		BigDecimal factor = selisih.multiply(new BigDecimal(Math.random()));

		return new Date((factor.add(decFrom)).longValue());
	}

	public static void main(String[] args) throws Exception {
		RandomDateGenerator rdg = new RandomDateGenerator();
		rdg.setSebelum(new SimpleDateFormat("dd MM yyyy").parse("17 08 1978"));
		rdg.setSesudah(new SimpleDateFormat("dd MM yyyy").parse("17 08 1990"));
		rdg.setRepetition(10);
		rdg.start();
	}
}

may the SOURCE be with you.

Wassalam.