Saturday, June 02, 2007

JPanel with gradient background

Thanks Sun for your great Swing framework. You've to know that Swing is the most powerful GUI framework I've seen in my life. Well architecture and extraordinary think for being very usable. The well MVC model, the ease of creating custom GUI components all of this should reflect the power of Swing. Check my blog I'll soon write down tips and lessons for having nice GUI using swing.

Let's start



First you've to know some about Swing painting mechanism. Each Swing component - JComponent - has a paint method which has a role of calling three main method to draw the component right

  1. paintComponent(Graphics g) this function is responsible for drawing the status of the component. Think of the JButton's paintComponent, it's responsible for drawing the JButton in three ways: normal, mouse over, clicked. The button is aware of it's status so it could paint itself right.
  2. paintBorder(Graphics g) this is the one responsible for drawing the border of your component, in case it have a border.
  3. paintChildren(Graphics g) this one is called to draw children components of the current component. For example, a panel which has two buttons. This function would call the paint of each component attached to this component.
For you to implement your custom drawing. You've to override "paintComponent", you've not to touch "paint", "paintBorder" nor "paintChildren".

Read this if you've difficulties understanding http://java.sun.com/products/jfc/tsc/articles/painting/

Secondly you've to know about Opacity. What is opacity? An opaque thing is difficult to see through - your room walls -. In Java each JComponent defines it's opacity. If it's opaque so you can't see through. The else is you can see through.

For example we've two panels. p1 and p2. p2 is a child of p1. p1's background is red, p2's background is green.

If the two panels are opaque you should see a green color; as p2 is opaque and you can't see p1 through it.

If p1 is opaque and p2 is not. You'll see a red color. whatever p2's background is you'll see a red color. As p2 is not opaque you can see through.

Read this if you didn't get it
http://mindprod.com/jgloss/opaque.html
http://java.sun.com/javase/6/docs/api/javax/swing/JComponent.html#isOpaque()

Thirdly we're now to start coding.

Open your favorite IDE which is Eclipse for me.
And follow the next steps

1- Create a new Java project and name it "Gradient Panel"
2- Create a new package - to organize your work - and name it "gradient"
3- Create a new class name it "GradientPanel".
4- You should have something like :



5- Now open you editor and type in the following code

package gradient;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

/**
* GradientPanel is a class with a gradient background, put your non-opaque objects over it and enjoy.
* @author Mohammad Abou-Basha
*
*/
public class GradientPanel extends JPanel
{

private Color startColor;

private Color endColor;

public GradientPanel()
{
this( Color.GRAY , Color.WHITE );
}

public GradientPanel( Color startColor , Color endColor )
{
super();
this.startColor = startColor;
this.endColor = endColor;
}

@Override
protected void paintComponent( Graphics g )
{
super.paintComponent( g );
int panelHeight = getHeight();
int panelWidth = getWidth();
GradientPaint gradientPaint = new GradientPaint( 0 , 0 , startColor , panelWidth , panelHeight , endColor );
if( g instanceof Graphics2D )
{
Graphics2D graphics2D = (Graphics2D)g;
graphics2D.setPaint( gradientPaint );
graphics2D.fillRect( 0 , 0 , panelWidth , panelHeight );
}
}
}


Now we've a gradient panel. We have to create a demo and try playing.

6- Create a new Frame, name it "GradientPanelDemo". For the ease you can use the visual editor.
7- Drag a new bean and select the GradientPanel. The code should be something like that

package gradient;

import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class GradientPanelDemo extends JFrame
{

private static final long serialVersionUID = 1L;
private JPanel jContentPane = null;
private GradientPanel gradientPanel = null;

/**
* This is the default constructor
*/
public GradientPanelDemo()
{
super();
initialize();
}

/**
* This method initializes this
*
* @return void
*/
private void initialize()
{
this.setSize( 300 , 200 );
this.setContentPane( getJContentPane() );
this.setTitle( "JFrame" );
}

/**
* This method initializes jContentPane
*
* @return javax.swing.JPanel
*/
private JPanel getJContentPane()
{
if( jContentPane == null )
{
jContentPane = new JPanel();
jContentPane.setLayout( new BorderLayout() );
jContentPane.add(getGradientPanel(), BorderLayout.CENTER);
}
return jContentPane;
}

/**
* This method initializes gradientPanel
*
* @return gradient.GradientPanel
*/
private GradientPanel getGradientPanel()
{
if( gradientPanel == null )
{
gradientPanel = new GradientPanel();
}
return gradientPanel;
}

}

8- You should see that in your visual editor



9-Now let add some buttons and text stuff and check the result


Here's the component hierarchy


Preview 2

Ooh, why is the last panel "jPanel" gray!!
Don't you remember? I told you about opacity. Simply make this panel not opaque and check the result
jPanel.setOpaque( false );


Preview after setting the panel opacity to false

Use this constructor to define your own colors
gradientPanel = new GradientPanel( Color.RED , Color.YELLOW );




This was the first tip having great Swing GUI.
Click here to get the full project.

Comments are welcomed, so feel free.



References
http://java.sun.com/products/jfc/tsc/articles/painting/
http://java.sun.com/javase/6/docs/api/java/awt/GradientPaint.html

13 comments:

Ayman Emam said...

Good work ladido, i like the post, go on :) nice work.

Mohammad Abou-Basha said...

You're welcome Ayman :)

Sara said...

Very nice, i like it :)

m.hewedy said...

Gazak ALLAH khayran,
very great work, and good control with GUI components the most thing in Java that I neglect :D

zebra said...

Hi ladido,

I had to change the LAF for a swing application and your post helped me to understand faster. Also I did not know about GradientPaint. Thanks for your information sharing.

zebra said...

Hi ladido,

I had to change the LAF for a swing application and your post helped me to understand faster. Also I did not know about GradientPaint. Thanks for your information sharing.

zebra said...

Hi ladido,
I had to change the LAF for a swing application and your post helped me to understand faster. Also I did not know about GradientPaint. Thanks for you information sharing.

Anonymous said...

Your blog keeps getting better and better! Your older articles are not as good as newer ones you have a lot more creativity and originality now keep it up!

Anonymous said...

I wish not acquiesce in on it. I think nice post. Expressly the title attracted me to review the unscathed story.

Anonymous said...

Amiable post and this post helped me alot in my college assignement. Thanks you as your information.

Faizal Luthfi said...

Jazaakallahu khairan katsiran.. Amien

Anonymous said...

thanks for this nice post 111213

Anonymous said...

hi, good site very much appreciatted