Simple REST client in java

Today most of the mobile applications that used to communicate to some server use REST services. These services are also common practice to use with JavaScript or jQuery. Right now I know 2 ways to create client for REST service in java and in this article I will try to demonstrate both the ways I know hoping that it will help someone in some way.

1. Using Apache HttpClient

The Apache HttpClient library simplifies handling HTTP requests. To use this library you have to download the binaries with dependencies from their website.
Here is the code for HTTP GET method:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
public class Test {
	public static void main(String[] args) throws ClientProtocolException, IOException {
		HttpClient client = new DefaultHttpClient();
		HttpGet request = new HttpGet("http://restUrl");
		HttpResponse response = client.execute(request);
		BufferedReader rd = new BufferedReader (new InputStreamReader(response.getEntity().getContent()));
		String line = "";
		while ((line = rd.readLine()) != null) {
		  System.out.println(line);
		}
	}
}

And for Post method; for sending simple string in post:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
public class Test {
	public static void main(String[] args) throws ClientProtocolException, IOException {
		HttpClient client = new DefaultHttpClient();
		HttpPost post = new HttpPost("http://restUrl");
		StringEntity input = new StringEntity("product");
		post.setEntity(input);
		HttpResponse response = client.execute(post);
		BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
		String line = "";
		while ((line = rd.readLine()) != null) {
			System.out.println(line);
		}
	}
}

You can also send full JSON or XML of a POJO by putting String representing JSON or XML as a parameter of StringEntity and then set the input content type. Something like this:

StringEntity input = new StringEntity("{\"name1\":\"value1\",\"name2\":\"value2\"}"); //here instead of JSON you can also have XML
input.setContentType("application/json");

For JSON you can use JSONObject to create string representation of JSON.

JSONObject json = new JSONObject();
json.put("name1", "value1");
json.put("name2", "value2");
StringEntity se = new StringEntity( json.toString());

And for sending multiple parameter in post request:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
public class Test {
	public static void main(String[] args) throws ClientProtocolException, IOException {
		HttpClient client = new DefaultHttpClient();
		HttpPost post = new HttpPost("http://restUrl");
		List nameValuePairs = new ArrayList(1);
		nameValuePairs.add(new BasicNameValuePair("name", "value")); //you can as many name value pair as you want in the list.
		post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
		HttpResponse response = client.execute(post);
		BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
		String line = "";
		while ((line = rd.readLine()) != null) {
			System.out.println(line);
		}
	}
}

2. Using Jersey

Jersey is the reference implementation forJSR-311 specification, the specification of REST support in Java. Jersey contains basically a REST server and a REST client. it provides a library to communicate with the server producing REST services. For http get method:

import java.io.IOException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import org.apache.http.client.ClientProtocolException;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
public class Test {
	public static void main(String[] args) throws ClientProtocolException, IOException {
		ClientConfig config = new DefaultClientConfig();
		Client client = Client.create(config);
		WebResource service = client.resource(UriBuilder.fromUri("http://restUrl").build());
		// getting XML data
		System.out.println(service. path("restPath").path("resourcePath").accept(MediaType.APPLICATION_JSON).get(String.class));
		// getting JSON data
		System.out.println(service. path("restPath").path("resourcePath").accept(MediaType.APPLICATION_XML).get(String.class));
	}
}

There are also other media formats in which you can get the response like PLAIN or HTML.
And for HTTP POST method:

import java.io.IOException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriBuilder;
import org.apache.http.client.ClientProtocolException;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.core.util.MultivaluedMapImpl;
public class Test {
	public static void main(String[] args) throws ClientProtocolException, IOException {
		ClientConfig config = new DefaultClientConfig();
		Client client = Client.create(config);
		WebResource webResource = client.resource(UriBuilder.fromUri("http://restUrl").build());
		MultivaluedMap formData = new MultivaluedMapImpl();
		formData.add("name1", "val1");
		formData.add("name2", "val2");
		ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, formData);
		System.out.println("Response " + response.getEntity(String.class));
	}
}

If you are using your POJO in the POST then you can do something like following:

ClientResponse response = webResource.path("restPath").path("resourcePath").
type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).post(ClientResponse.class, myPojo);
System.out.println("Response " + response.getEntity(String.class));

Here myPojo is an instance of custom POJO class.
You can also use Form class from Jersey to submit multiple parameters in POST request:

import java.io.IOException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import org.apache.http.client.ClientProtocolException;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.representation.Form;
public class Test {
	public static void main(String[] args) throws ClientProtocolException, IOException {
		ClientConfig config = new DefaultClientConfig();
		Client client = Client.create(config);
		WebResource service = client.resource(UriBuilder.fromUri("http://restUrl").build());
		Form form = new Form();
		form.add("name1", "value1");
		form.add("name2", "value1");
		ClientResponse response = service.path("restPath").path("resourcePath").
		type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, form);
		System.out.println("Response " + response.getEntity(String.class));
	}
}

Let me know if you find any difficulty while using these code samples. Feel free to comment. 🙂

Advertisements

Trying Architexa for the first time

Architexa is a really useful tool for generating UML diagrams for Java projects in Eclipse. Most UML tools out there give you functionality of generating classes from the diagram you have created. But in Architexa you have a reverse functionality; it generates diagrams from existing code.  It helps a team to understand and document collaboratively a large Java code base. Starting from today, Architexa is available for free for individuals to use, and this post talks about my experience using it – how I used it?, which features I used?, and what I think of it?

Why should one use Architexa?

If the answer to any of following is yes for you then you should go for Architexa:

  1. Working with a new project or difficulty in introducing an existing product to a new team member.
  2. Finding it hard to understand the architecture of your code.
  3. Exploring unfamiliar code to determine its dependencies, relationships, interactions, and behavior within a codebase.
  4. Trouble finding a starting point in a large codebase.
  5. Wasting time deciphering complex code or documenting about code.

If your answer to any of the above questions is YES then you must go for Architexa. It will handle all these difficulties for you. Architexa helps you create UML diagrams directly from the code in just a single click. So making UML diagrams is way easier than before. It can create layered-diagrams, class, and sequence diagrams. These diagrams become the base for effective discussions and act as useful documentation for the project. Architexa allows you to add and edit Java Doc from code and other notes right next to the diagram.

My experience with Architexa:

(How I used Architexa?)

 

 

As do many other Java developers out there I also use Eclipse as an IDE for Java development and face some of the issues listed above in development due to lack of documentation about the project. I was already using an Eclipse tool/plugin for UML diagrams in Eclipse, but that tool was only very helpful if you are the one who starts the project. If you have been given a project that is already developed and does not have enough documentation to understand its flow and code then that tool doesn’t help me much.

About few days ago I got an email about Architexa, a tool for generating UML diagrams for Java projects in Eclipse. At first it looked like a normal tool of generating UML diagrams and I thought why download and use it as I was already using a tool to do same thing? But then I came to know about its functionality of directly generating UML diagrams from the existing code and this feature forced me to try Architexa once. And as I was expecting this is really a great and helpful tool for understanding the top level architecture of a large project. And as an advantage it provides functionalities of sharing diagrams or exporting diagrams as pictures.

I tried Architexa with one of our currently on-going projects and I would like to share my experience about how I used this tool and what features I liked most. I have written how I installed it and used it. I have listed what features I liked and used and would like to suggest you use those features. I have also written suggestions from my side that I would like to see in the product.

Download and Installation:

Download and installation of Architexa is very easy. One can start this procedure by registering on their site here: http://www.architexa.com/start. This registration is required as when you complete the installation it asks for this registered username and password. After this registration steps complete it will take you to the page where you find information on how to install Architexa on your Eclipse, which is also easy understandable and easy to follow. You also have to follow an email verification process which I guess is a very known and common practice to protect from spam and everybody is familiar with it. We have also installed extended features and the in-house group server to see how they all works together.

Generating my first diagram:

Before generating diagrams you first have to configure Architexa indexing. You can configure it after successful installation and account validation or later in Preferences.  After this configuration you are ready to generate diagrams.  You will see a Cheat Sheets view of Architexa when you install it, where you find and explanation of steps to get started with the different capabilities of Architexa.

Layered-diagrams:

To generate a layered-diagram, you just have to right click on project and select Open in diagram->Layered diagram. Layered diagram gives a good representation of project packages and dependencies between them. It’s a good diagram to have a quick overview of the project. It is very good in displaying a particular classes’ dependency from a package view, and how packages are dependent on each other. Some features that I used and liked in layered diagrams are:

  • Size of the module is drawn based on code inside it and they are also placed in layered style such that higher layered modules are dependent on lower layered modules. When you hover on any class or package it shows it’s dependencies by arrows to other class and/or packages.  Also those packages are highlighted to get proper focus on it. It helps us to decide which modules will get affected if do change in a module.
  • Double clicking on packages will show the classes and packages inside it.
  • You can easily add new packages, classes, general connections, actor, database and/or comments directly from this diagram.

Class and sequence diagrams:

Generating class and sequence diagrams is also easy, right click on some class then click on Open in diagram->Class diagram or Open in diagram->Sequence diagram.  When you do this it draws a diagram with only one selected class, no any other classes to make it messy. Now you can add things you need by dragging and dropping classes or by exploring class members/methods and their dependencies. Also it uses icons for classes, members and methods that Eclipse uses, so it becomes easy to understand it.

A sequence diagram is a good representation of call hierarchy of methods or members of a class. By this you can easily see which methods/members are called and used by which other classes. To demonstrate the possible flow of control that a system could take depending on various conditions or tests, Architexa displays loops, iterations, and conditional statements in sequence diagrams.

A class diagram gives information about relationships and dependencies of classes with each other. It gives an overview of which class inherits from which class or what classes subclass it. Some features that I used and liked are in these diagrams are:

  • You can easily go to the code of particular class or method by just double clicking on it.
  • You can add new methods and/or members to a class. You can also add method call, inheritance, method override, actor, database, comments in these diagrams.
  • In sequence you can see differences in a file if 2 or more members of a team are working on same file. It shows difference in the diagram which is in my opinion a very cool feature.
  • Sequence diagrams are also integrated with the debugger.

Sharing diagrams:

Architexa provides a functionality to share created diagrams to team members. To share diagram you have to create a group on its server. By sharing diagrams your team members can easily access the documents whenever they want to. Creating groups is also easy, I have created a group from the website, but one can also create it from Eclipse. After creating a group you have to save your diagram in it. When you press CTRL + S to save a diagram it will open a dialog with 3 options:

  1. Save diagram on local disk
  2. Save diagram on private server
  3. Save diagram on community server

3rd option is for saving a diagram on their server. When you click on it, you will see Upload to server view. Here you can give it a name and choose a group to share this diagram with.

The other way to share is by email. I have not tried this functionality yet and so am not able to write much about it.

Some suggestions:

  1. In layered-diagram, if I drag and drop packages then sometimes it results in duplicate packages in the same group.
  2. In layered-diagram, sometimes an empty group of packages gets hidden and sometimes it stays visible.  Not sure if it’s intended but it doesn’t look consistent to me so would like to see a change in this.
  3. Diagrams also include method calls to Java’s default classes like Map or String. What I think is generally people don’t want to know about these classes and calls to methods of these classes as they can be considered as a part of the implementation and not documentation. It’s a part of how one has done the task. Everything else in this diagram is cool.
  4. Fonts used for class names in layered diagram are quite bigger relative to package names; it will be good if it can become smaller.
  5. If you close Eclipse without saving the diagrams, it doesn’t notify or alerts you about first saving diagrams and then close Eclipse. It should alert if one is closing Eclipse without saving diagrams.

Summary

Architexa is a good tool for UML diagrams in Eclipse for Java development. It is very  easy and simple to use. Once a class is in a diagram, it is always kept up to date so no need to refresh diagrams every time you change something. And the graphs are also very readable. If you have a large team in which members keep getting changed or you are the one who is responsible for understanding already written large codes then this is the must-use tool for you. Currently Architexa is only available for Java. Though they also have a prototype for C/C++. If you have used it for a new project from the beginning then it will become very easy to document your project, share the diagrams, code change reviews, and much more.

Architexa also has many other features that I have not used yet. For more information on Architexa visit their website: http://www.architexa.com/

Chat bubble in java swing

chatBubble

This article will explain you “how to draw chat bubble in  java swing application?” Chat bubble is same as call-out or thought bubble. Today most of the chat application is showing conversion in this format, so this article will help you to do the same in desktop application made in java swing.

Following class is used to draw first chat bubble: (Arrow at the left side of bubble)

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JPanel;
/**
 * @author harsh
 */
public class LeftArrowBubble extends JPanel {
   private static final long serialVersionUID = -5389178141802153305L;
   private int radius = 10;
   private int arrowSize = 12;
   private int strokeThickness = 3;
   private int padding = strokeThickness / 2;
   @Override
   protected void paintComponent(final Graphics g) {
      final Graphics2D g2d = (Graphics2D) g;
      g2d.setColor(new Color(0.5f, 0.8f, 1f));
      int x = padding + strokeThickness + arrowSize;
      int width = getWidth() - arrowSize - (strokeThickness * 2);
      int bottomLineY = getHeight() - strokeThickness;
      g2d.fillRect(x, padding, width, bottomLineY);
      g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING,   RenderingHints.VALUE_ANTIALIAS_ON));
      g2d.setStroke(new BasicStroke(strokeThickness));
      RoundRectangle2D.Double rect = new RoundRectangle2D.Double(x, padding, width, bottomLineY, radius, radius);
      Polygon arrow = new Polygon();
      arrow.addPoint(20, 8);
      arrow.addPoint(0, 10);
      arrow.addPoint(20, 12);
      Area area = new Area(rect);
      area.add(new Area(arrow));
      g2d.draw(area);
   }
}

Following code is to draw second chat bubble. (Arrow at the right side of bubble):

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JPanel;
/**
 * @author harsh
 */
public class RightArrowBubble extends JPanel {
   private static final long serialVersionUID = -5389178141802153305L;
   private int strokeThickness = 3;
   private int radius = 10;
   private int arrowSize = 12;
   private int padding = strokeThickness / 2;
   @Override
   protected void paintComponent(final Graphics g) {
      final Graphics2D g2d = (Graphics2D) g;
      g2d.setColor(new Color(0.5f, 0.5f, 1f));
      int bottomLineY = getHeight() - strokeThickness;
      int width = getWidth() - arrowSize - (strokeThickness * 2);
      g2d.fillRect(padding, padding, width, bottomLineY);
      RoundRectangle2D.Double rect = new RoundRectangle2D.Double(padding, padding, width, bottomLineY,  radius, radius);
      Polygon arrow = new Polygon();
      arrow.addPoint(width, 8);
      arrow.addPoint(width + arrowSize, 10);
      arrow.addPoint(width, 12);
      Area area = new Area(rect);
      area.add(new Area(arrow));
      g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
      g2d.setStroke(new BasicStroke(strokeThickness));
      g2d.draw(area);
   }
}

And here is the code for using above 2 classes:

import java.awt.HeadlessException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
 * @author harsh
 */
public class TestPanel extends JPanel {
	private static final long serialVersionUID = 9029457020704524363L;
	private JLabel messageLbl1, userImageLbl1, messageLbl, userImageLbl;
    private JPanel msgPanel1, msgPanel;
    String userImageUrl = "http://cdn1.iconfinder.com/data/icons/nuvola2/22x22/apps/personal.png";
    public TestPanel() throws MalformedURLException {
        userImageLbl = new JLabel();
        msgPanel = new LeftArrowBubble();
        messageLbl = new JLabel();
        messageLbl1 = new JLabel();
        msgPanel1 = new RightArrowBubble();
        userImageLbl1 = new JLabel();

        userImageLbl.setIcon(new ImageIcon(new URL(userImageUrl)));
        messageLbl.setText("Hi, How are you?");

        GroupLayout msgPanelLayout = new GroupLayout(msgPanel);
        msgPanel.setLayout(msgPanelLayout);
        msgPanelLayout.setHorizontalGroup(
            msgPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(msgPanelLayout.createSequentialGroup()
                .addGap(21, 21, 21)
                .addComponent(messageLbl)
                .addContainerGap(162, Short.MAX_VALUE))
        );
        msgPanelLayout.setVerticalGroup(
            msgPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(msgPanelLayout.createSequentialGroup()
                .addComponent(messageLbl)
                .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        messageLbl1.setIcon(new ImageIcon(new URL(userImageUrl)));
        userImageLbl1.setText("I'm Good.");

        GroupLayout jPanel1Layout = new GroupLayout(msgPanel1);
        msgPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap(171, Short.MAX_VALUE)
                .addComponent(userImageLbl1)
                .addGap(22, 22, 22))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(userImageLbl1)
                .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        GroupLayout layout = new GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(userImageLbl)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                    .addComponent(msgPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(msgPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addComponent(messageLbl1)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                    .addComponent(userImageLbl)
                    .addComponent(msgPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                    .addComponent(messageLbl1)
                    .addComponent(msgPanel1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
                .addContainerGap(22, Short.MAX_VALUE))
        );
    }
    public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				try {
					JOptionPane.showMessageDialog(null, new TestPanel());
				} catch (HeadlessException e) {
					e.printStackTrace();
				} catch (MalformedURLException e) {
					e.printStackTrace();
				}
			}
		});
	}
}

At least try it once and feel free to comment about it. 🙂

JTextField with image inside it

The final output will look like following:

textBox_with_image

I applied same logic as one will do with css if it was meant for website. Just 2 simple steps:

  1. Draw the image as background in text box.
  2. Set margin of image width for text inside text box.

For the first step one have to override painComponent method of JTextField as follow:

final BufferedImage image = ImageIO.read(Test.class.getClassLoader().getResource("img/user.png"));
JTextField textField = new JTextField() {
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int centerPoint = (getHeight() - image.getHeight())/2;
        g.drawImage(image, 0, centerPoint, this);
    }
};

And for the second step:

textField.setMargin(new Insets(0, image.getWidth(), 0, 0));

That’s it. When you use it you will see a text box with image at it’s left as shown in above image.

If you are using custom border for text field and and if is overlapping the image then don’t panic just shift your image slightly as follows:

Get textField’s border inset from the left:

final int borderInset = border.getBorderInsets(new JTextField()).left; // here border is the object indicating Border of JTextField.

Now add it to ‘x’ point in drawImage and serMargin method:

//inside first step
g.drawImage(image, borderInset, centerPoint, this);

//second step
textField.setMargin(new Insets(0, borderInset + image.getWidth(), 0, 0));

As final point don’t forget to increase text field’s height according to your image. If you don’t want to bother to calculate then following line might be helpful to you:

textField.setPreferredSize(new Dimension(textField.getWidth(), image.getHeight() + 10));

🙂

Infinite progress bars in swing

Following are some infinite progress bars built in java swing 2d using JPanel’s paintComponent(Graphics g) method.

Windows XP

I have seen this kind of loading icon while setting up windows XP, you might have also seen it:
xp_loader
So how one can simulate same in swing? Here is the answer:

/**
 * Some custom infinite progress bars in JPanel using Graphics2D object.
 * @author harsh
 */
public class CustomInfiniteProgressBar extends JPanel {
    private static final long serialVersionUID = 223086939802246968L;
    private static final int DELAY = 100;
    private static final int MAX_AMOUNT = 100;
    private static final int SPACE = 30;
    private static final int NUMBER_OF_RECTS = 5;
    private Timer timer;
    private int value = 0, darkRect = 0;

    public CustomInfiniteProgressBar() {
        timer = new Timer(DELAY, new TimerActionListener());
        timer.start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        // draw rectangular progress
        int paddingToFrameBorders = 10; //dummy values for position
        int smallerSize = 5, largerSize = 10; //dummy values for rectangle size

        int rectX, rectY;
        for (int i = 0; i < NUMBER_OF_RECTS; i++) {
            rectX = paddingToFrameBorders + i * SPACE;
            rectY = paddingToFrameBorders;
            if(darkRect == i) {
                g2d.fillRect(rectX, rectY, largerSize, largerSize);
            } else {
                // to center smaller rectangle respective to larger rectangle.
                rectX += (largerSize - smallerSize) / 2;
                rectY += (largerSize - smallerSize) / 2;

                g2d.drawRect(rectX, rectY, smallerSize, smallerSize);
            }
        }
    }

    /**
    * Action Listener of Timer.
    */
    private class TimerActionListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            value++;
            if(value == MAX_AMOUNT) { // you can have some condition here to stop the timer.
                timer.stop();
            }
            darkRect = (value % NUMBER_OF_RECTS);
            repaint();
        }
    }
}

Circular infinite progress bar

circles_loading

For this you just have to replace rectangle drawing logic to circle drawing logic and its done:

// global constants
private static final int RADIUS = 30;
private static final int NUMBER_OF_CIRCLES = 10;

private int darkCircle = 0;

//inside paintComponent(g) method
int centerX, centerY; centerX = centerY = 75; //dummy values for position
int circularX, circularY;
for (int i = 0; i < NUMBER_OF_CIRCLES; i++) {
    circularX = centerX + (int) (RADIUS * Math.sin((360 / NUMBER_OF_CIRCLES) * i * 3.14 / 180));
    circularY = centerY + (int) (RADIUS * Math.cos((360 / NUMBER_OF_CIRCLES) * i * 3.14 / 180));
    if(darkCircle == i) {
        g2d.fillOval(circularX, circularY, 10, 10);
    } else {
        g2d.drawOval(circularX, circularY, 10, 10);
    }
}

// in timer action class
darkCircle = NUMBER_OF_CIRCLES - 1 - (value % NUMBER_OF_CIRCLES);

Another example of such progress bar:
circular_loaing_2

for this use following code inside paintComponent(g) everything else will same as above:

//inside paintComponent(g) method
BasicStroke drawingStroke = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{9}, 0);
g2d.setStroke(drawingStroke);
for (int i = 0; i < NUMBER_OF_CIRCLES; i++) {
    circularX = centerX + (int) (RADIUS * Math.sin((360 / NUMBER_OF_CIRCLES) * i * 3.14 / 180));
    circularY = centerY + (int) (RADIUS * Math.cos((360 / NUMBER_OF_CIRCLES) * i * 3.14 / 180));
    if(darkCircle == i) {
        g2d.setColor(new Color(100, 200, 150));
        g2d.drawLine(circularX, circularY, circularX + 10, circularY + 10);
    } else {
        g2d.setColor(Color.black);
        g2d.drawLine(circularX, circularY, circularX + 10, circularY + 10);
    }
}

Arrow shape for progress bar

I’m not sure if following can be used as progress bar, but it can be used for highlighting something or some similar kind of task.
arrow loading highlighting
The code for this as follows:

// inside paintComponent(g) method
for (int i = 0; i < NUMBER_OF_RECTS; i++) {
    if(darkRect == i)
        g2d.fill(getArrowShape(i * 10, 50, 150));
    else
        g2d.draw(getArrowShape(i * 10, 50, 150));
}

// the getArrowShape method
/**
 * Returns arrow shape(a triangle).
 * Points are:
 * A (x + i, y)
 * | \
 * |  \
 * |   \
 * |    C ((x + 10) + i, (y + 10))
 * |   /
 * |  /
 * | /
 * B (x + i, (y + 20))
*/
private Shape getArrowShape(int i, int x, int y) {
    final Polygon result = new Polygon();
    result.addPoint(x + i, y); // A
    result.addPoint(x + i, (y + 20)); // B
    result.addPoint((x + 10) + i, (y + 10)); // C
    return result;
}

That’s all for now.
Hope You like it. 🙂

Drawing Android icon in swing

Hi, I tried to make android robot in java swing. I found 2 ways of doing this:

  1. Get android robot image, and show it as background in panel.
  2. Draw whole robot shape in java 2d graphics.

Here I will demonstrate the second way. The final output will be like this:

android_icon_in_java_swing

There are mainly five shapes used in this:

  1. A half circle shape for the head.
  2. Round rectangles for hands and legs.
  3. Big rectangle for the body.
  4. Lines for antennas.
  5. Small white circles for eyes.

So here is how you do it in java swing using Graphics2d object.  The color used is “r=153, g= 204,  b=0”:

g2d.setColor(new Color(153, 204, 0));

1. First for the head, the half circle:

g2d.fillArc(75, 55, 150, 125, 0, 180); // head circle

2. The body, a big rectangle. But as in the icon the bottom of body has round corner so as a hack added a round rectangle just after the body, with slightly overlap for not showing top round corners of second rectangle.

g2d.fillRect(75, 125, 150, 150); // body
g2d.fillRoundRect(75, 260, 150, 20, 20, 20); // cause bottom of body has round corners

3. Now for the had. It is quite easy, just need to draw 2 round rectangles and position them at the right point.

g2d.fillRoundRect(40, 120, 30, 110, 30, 30); // right hand
g2d.fillRoundRect(230, 120, 30, 110, 30, 30); // left hand

4. For the legs, do the same as done for hand, draw 2 round rectangles with smaller height and position changed to bottom of body.

g2d.fillRoundRect(95, 260, 30, 70, 30, 30); // right leg
g2d.fillRoundRect(175, 260, 30, 70, 30, 30); // left leg

5. For the antennas:

g2d.drawLine(125, 65, 100, 40); // right head antenna
g2d.drawLine(175, 65, 200, 40); // left head antenna

6. And finally for the eyes

g2d.setColor(Color.white); // change the color for the eyes
g2d.fillOval(115, 80, 10, 10); // left eye
g2d.fillOval(175, 80, 10, 10); // right eye

The whole code combined will look like this:

@Override
protected void paintComponent(Graphics g1) {
	Graphics2D g2d = (Graphics2D) g1;
	g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
	g2d.setColor(new Color(153, 204, 0));
	g2d.fillArc(75, 55, 150, 125, 0, 180); // head circle
	g2d.fillRect(75, 125, 150, 150); // body
	g2d.fillRoundRect(75, 260, 150, 20, 20, 20); // cause bottom of body has round corners
	g2d.fillRoundRect(40, 120, 30, 110, 30, 30); // right hand
	g2d.fillRoundRect(230, 120, 30, 110, 30, 30); // left hand
	g2d.fillRoundRect(95, 260, 30, 70, 30, 30); // right leg
	g2d.fillRoundRect(175, 260, 30, 70, 30, 30); // left leg
	g2d.drawLine(125, 65, 100, 40); // right head antenna 
	g2d.drawLine(175, 65, 200, 40); // left head antenna

	g2d.setColor(Color.white);
	g2d.fillOval(115, 80, 10, 10); // left eye
	g2d.fillOval(175, 80, 10, 10); // right eye
}

Hope you like it. 😀


And for the people who are interested in first way, here is how you do it. The first way is quite easy, you need to use drawImage method of Graphics.

@Override
protected void paintComponent(Graphics g) {
	Graphics2D g2d = (Graphics2D) g;
	BufferedImage img = null;
	try {
		img = ImageIO.read(TestAndroidIcon.class.getClassLoader().getResource("./android.png"));
		int w = img.getWidth(null);
		int h = img.getHeight(null);
		BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		Graphics g1 = bi.getGraphics();
		g1.drawImage(img, 0, 0, null);
		g2d.drawImage(bi, null, 0, 0);
	} catch (IOException e) {
		e.printStackTrace();
	}
}

🙂

Circular progress bar in Java Swing

Had you ever got thought of creating a circular progress bar in swing? yes, huh. At first it sounds difficult but then when you start building it then you might found that it is very easy if you have already made an clock application. 🙂

Final result would be like this:

circlePB

We will start by creating a circle animation by use of Timer and overriding paintComponent method of a JPanel:

/**
 * Circular progress bar panel.
 * @author harsh
 */
public class CircularProgressBar extends JPanel {
      private final static int MAX_PROGRESS_AMOUNT = 100;
      private static final int DELAY = 50;
      private Timer timer;
      private int prgValue = 0;

      public CircularProgressBar() {
            timer = new Timer(DELAY, new MyChangeListener());
            timer.start();
      }

      @Override
      protected void paintComponent(Graphics g) {
             Graphics2D g2 = (Graphics2D) g;
             g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
             if (prgValue <= MAX_PROGRESS_AMOUNT) {
                   g.setColor(Color.blue);
                   int angle = -(int) (((float) prgValue / MAX_PROGRESS_AMOUNT) * 360);
                   g.fillArc(0, 0, getWidth(), getHeight(), 90, angle);

            }
     }

     class MyChangeListener implements ActionListener {
         @Override
         public void actionPerformed(ActionEvent arg0) {
             prgValue++;
             repaint();
             if (prgValue >= MAX_PROGRESS_AMOUNT)
                  timer.stop();
        }
    }
}

if you run this you will see something like this:

It was easy, huh. Now the challenging part is to remove inner circular part and make it to view like first image. For that I decide to draw another circle with the same color as background. So here it is:


g2.setColor(getBackground());
g.fillArc(getWidth() / FRACTION / 2, getHeight() / FRACTION / 2,
getWidth() * (FRACTION - 1) / FRACTION, getHeight() * (FRACTION - 1) / FRACTION, 92, angle);

Add this code to paintComponent method and once again run the program. Now you will see something like in first picture.  In above code FRACTION is the width you want for your progress bar. Lesser value of fraction, wider the progress bar. One more difference in 2 fillArc method is in the start angle, in first method it is 90 and in second its 92. This difference will be width of the middle hand.

Here is the testing code:

JFrame frame = new JFrame("Circular Progress Bar by Harry Joy");
frame.add(new CircularProgressBar());
frame.setSize(350, 350);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);

Hope you like it. 🙂

%d bloggers like this: