Friday, July 20, 2007

Using Swing Worker

In any GUI application the most important thing is responsiveness to user action. To keep our application responsive requires careful design and coding. As we know all the swing related event will be processed by only one thread called AWT event dispatcher thread. Its the job of this thread to do painting of components shown on the screen. If you block AWT event thread for quite sometime it will make your application look unresponsive.

In this post, I will share my experience with this and how I overcame it. I will also show you a small code snippet, which you can use it other Swing Application.

To make your application look responsive you should not do heavy weight operation in AWT thread. For example, on click of a button you need to fetch data from a different network, which will take sometime, so never do this in AWT thread. similarly if you add 2 number on click of a button, you can do it in AWT dispatch thread itself.

In the sample application that we are going to design, we will have a text box which will be filled by data (after doing heavy weight operation) . We will have 2 different buttons. One button will do the heavy weight operation in AWT Thread itself and other will use swing worker thread.

The code snippet below shows how it can be done.

import java.awt.GridBagConstraints;

import java.awt.GridBagLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;



import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JTextField;

import javax.swing.SwingUtilities;



public class SwingWorkerExample implements ActionListener

{

private JFrame frame;

JTextField field;



// create necessary user interface

public void init()

{

frame =
new JFrame("Test for Swing Worker");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setSize(300,300);

JPanel panel =
new JPanel(new GridBagLayout());



GridBagConstraints gc =
new GridBagConstraints();

field =
new JTextField(20);

gc.gridx = gc.gridy = 0;

panel.add(field,gc);

gc.gridy++;

JButton button =
new JButton("Do Work in background"); // button that does heavy work in background

button.setActionCommand("Work");

button.addActionListener(
this);

panel.add(button,gc);

gc.gridy++;

button =
new JButton("Do Work"); // button that does heavy work in awt thread ;(

button.setActionCommand("Work2");

button.addActionListener(
this);

panel.add(button,gc);

frame.setContentPane(panel);

frame.pack();

frame.setVisible(true);

}



// no click of a mouse button, called from AWT thread

public void actionPerformed(ActionEvent e)

{

if(e.getActionCommand().equals("Work"))

{

DelaySwingWorker worker =
new DelaySwingWorker(field);

worker.startWork();

}

else

{

try

{

Thread.sleep(10000);

field.setText(
"Data fetched : " + 25);

}

catch(Exception ex)

{

}

}

}



// out swing worker thread.

abstract public static class SwingWorker

{

public void startWork()

{

Thread t =
new Thread(new Runnable() { // create a new thread for heavy operation

public void run()

{

SwingWorker.
this.getData(); // let the swing worker get the data

SwingUtilities.invokeLater(new Runnable() {

public void run()

{

SwingWorker.
this.setData(); // update the data. This will be called from AWT thread

// so that you can safely do UI related update with the data

}

}
);

}

});

t.start();

}

abstract public void getData(); // abstract method will be implemented by the actual data fetchers

abstract public void setData();

}



// a sample class which simulates heavy weight operatoin

public static class DelaySwingWorker extends SwingWorker

{

private int data;

private JTextField field;



public DelaySwingWorker(JTextField f)

{

this.field = f; // field on which we will show the updated data.

}



public void getData()

{

try

{

Thread.sleep(10000); // heavy weight operation

data = 20; // data fetched

}

catch(Exception e)

{

}

}



public void setData()

{

field.setText(
"Data fetched is : " + 20);

}

}



public static void main(String[] args)

{

final SwingWorkerExample ex = new SwingWorkerExample();

SwingUtilities.invokeLater(
new Runnable() {

public void run()

{

ex.init();

}

});

}

}



Now run the application, click the first button, now minimize and maximize the application. It should look normal.

now click the second button and minimize and maximize the application, you should see window being grayed out. This is because AWT thread is blocked in a heavy weight operation and hence it cannot dispatch paint event to get the components painted.

Friday, July 13, 2007

Developer's life !

Its been quite a long since I updated my blog, because I don't find enough time (rather don't have a solid subject to write on! may be!) After reaching many developer's blog, who share their knowledge of software development, challenges in software development and solutions, I too have decided to write my experience in the process of software development. Yes I am new to this field where there are many experts, but the information that I may provide is nevertheless.

So here I am to share my experience, to share problems faced, bottle-necks I faced, hours spent on google trying to find the solution. Really don't know how regular I will be in updating my blog, but any how I have decided to give it a try.

To gain enough expertise in handling in a large software project is a big challenge and I have just now entered to this field. New jargons, new terms - but life is never interesting without new things. Apart from developing software as a job (that's what I'm getting paid for!), I would love to do that as a hobby as well.

The stuff that I recently developed can be used for converting java code to html (which does some keyword highlighting). You can use this software to convert java code to html so that it can be posted onto a blog or somewhere. You can download it from here

Currently I am working on software called JInspector. With this software you can inspect jar files, create jar files, assists you in creating MANIFEST files etc.,

My goals for creating this piece of software are:
1. Learn about JTree, creating custom cell renderer
2. Learn to use Zip Streams
3. last, but not the least, java swings.