Java Tips Weblog

  • Blog Stats

    • 1,099,858 hits
  • Categories

  • Archives

Custom Painting Approaches

Posted by Rob Camick on May 8, 2009

The basics of custom painting are explained in the section from the Swing tutorial on Custom Painting (see link below). The main idea is that you can customize a component by overriding its paintComponent() method. Typically, JComponent or JPanel will be overridden to do custom painting. A concern of many people is adding too much painting code to the paintComponent method which might result in excessive CPU usage or slow painting. Is this a valid concern and if so, then is there anything that can be done to minimize these problems?

First, lets look at the normal approach of painting which I’m going to refer to as “active” painting for the purposes of this blog. I call this “active” because painting is done directly on the component from scratch every time the paintComponent() method is invoked. Typically you would store information about the object to be painted in a List. Then, whenever the paintComponent() method is invoked you would iterate through the List and paint each object. Some advantages of this approach:

  • easy to use as all the painting code is contained in one place
  • allows for easy changing of the painting (ie. animation)
  • allows for easy undo of existing painting
  • the painting area can dynamically change in size

Some drawbacks of this approach:

  • can be slow depending on the complexity of the painting (ie. when painting requires lots of calculations or maybe animation of many objects)

I’m going to refer to the following alternative approach to painting as the “passive” approach. This is because the “active” painting will be done to a BufferedImage as required. Then, the paintComponent() method, whenever it is invoked, will “passively” draw the BufferedImage onto the component. Some advantages of this approach:

  • will result in faster painting. The relative performance increase will depend on the complexity of the painting.

Some drawbacks of this approach:

  • slightly harder to use as you need to create the BufferedImage and manage the painting to it
  • painting is done in multiple places
  • harder to undo painting
  • the painting area is fixed in size

The best way to understand the differences between the two approaches is to look at code and see each approach in action, so I have included code for each approach below. The functionality of each class is the same and attempts to address “how to”:

  • do static painting, in this case, by drawing a line of text.
  • change the painting dynamically, in this case, by adding rectangles of a different color.
  • reset the painting to its original state.

The differences between each approach are contained in the following three methods:

  • paintComponent – responsible for the custom painting whenever repaint is invoked on the panel. For the active approach you need to draw the static text and loop through the list to paint all the rectangles. For the passive approach you simply draw the buffered image.
  • mouseReleased – responsible for adding the dynamic rectangles. For the active approach you just add a rectangle to the list. For the passive approach you draw the rectangle on the buffered image right away.
  • clear – responsible for resetting the panel to its initial state. For the active approach you just clear the list. For the passive approach you need to recreate (or clear) the buffered image and then draw the static text.

Take the time to understand the code differences in each of the above methods and hopefully you will understand the differences in the two approaches.

Now, for fun, while using each of the programs try to duplicate my happy face drawing from the image below:

Custom-Painting-Approaches

Did you notice any performance difference between either of the programs? I doubt you will. It has been my experience that you would need to draw hundreds or thousands of rectangles before you would notice any difference. Therefore my suggestion would be to start with the normal or “active” approach to painting. Then, if you experience a problem you can switch to the alternate or “passive” approach of using a BufferImage.

If you want to have move fun try adding animation to each program. Something simple like randomly changing the location of each rectangle.

Get The Code

DrawOnComponent.java (Active)
DrawOnImage.java (Passive)

Related Reading

Java Tutorials: Performing Custom Painting
Java Tutorials: 2D Graphics

About these ads

5 Responses to “Custom Painting Approaches”

  1. Andre Uhres said

    For better performance with complicated components, “smart painting” could additionally be applied to both “active” and “passive” painting. Smart painting tries to use clip information to restrict painting to a smaller rectangle (Graphics#getClipBounds), instead of always painting the whole component. This requires the use of the “multi arguments” version of the repaint method, defining the rectangle to be updated.

    • Rob Camick said

      Yes, that would probably be better covered in an advance painting tutorial. Actually I plan on releasing a “LineNumber” component that can be used with a text area or text pane. So for a simple example of “smart painting” check back in a week or two.

      In general, I would still recommend you don’t worry about optimization until it is a problem.

  2. Anonymous said

    Nice

  3. Robocop said

    how to draw a circle and a rectangle in the same component

    • Rob Camick said

      This idea of this blog entry was to show the two different painting approaches. For your requirement, the easiest approach would probably be to change the DrawOnImage example. First you would need to add a couple components, maybe JRadioButtons (for Rectangle, Oval). Then in the painting code, you need to check to see with radio button is selected. Then you would use drawRect(…) or drawOval(…).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 88 other followers

%d bloggers like this: