Here is what I am trying to do. I have extended JButton and overwritten the paintComponent method creating my desired effect of a rounded edge button, and a color fading effect when the button is rolled over by a mouse. All that works great. My problem is that the JButton is still painting a white rectangle area as the images show.
I would like 1) the white corners to be gone and 2) the cetner of the button to show the panel behind it. Here is what I have tried:
1- when painting the button use getParent().getBackground() and paint the button first. This works great for opaque panels. However I would love this button to work on a partially or fully transparent panel. With transparent panels it paints the color, but on the white background hiding anything behind the panel (like an image).
2- I have tried many combinations of setOpaque(false) or setContentAreaFilled(false). I have tried this while calling super.paintComponent(g) and not calling it. None of those seem to work.
3- The button looks right when I don't use the method g2.clearRect(0,0,width,height) (clearing the graphics area before painting), but since the graphics object is never covered up the fade effect stops working after one rollover of the button.
4- I use a JLabel for the text and have tried setting it opaque or just not using it and the issue still remains. so I don't think that is the issue.
Since I only want an affect for the JButton and not other swing components I'm really hoping to avoid making my own ButtonUI.
Thanks and I hope this makes sense. Below is the code for my button.
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.*;
/**
* WButton.java
*
* An extension of JButton but with custom graphics
*
*/
public class WButton extends JButton{
private Timer timer;
private float[] background = {.3f,.6f,.8f,0f};
private boolean fadeUp = true;
private boolean fadeDown = false;
private JLabel label;
/**
* Default Constructor
*/
public WButton(){
super();
label = new JLabel();
setupButton();
}
/**
* Text constructor
*/
public WButton(String text){
super(text);
label = new JLabel(text);
setupButton();
}
/**
* common setup functions
*/
private void setupButton(){
timer = new Timer(24,new TimerAction(this));
label.setLabelFor(this);
add(label);
}
/**
* Set the background color
*/
@Override
public void setBackground(Color bg){
background = bg.getRGBComponents(background);
background[3] = 0f;
super.setBackground(new Color(background[0],background[1],
background[2],background[3]));
repaint();
}
/**
* get background
*/
@Override
public Color getBackground(){
if(background!=null)
return new Color(background[0],background[1],background[2],background[3]);
return new Color(.5f,.5f,.5f);
}
/**
* Set the font of the button
*/
@Override
public void setFont(Font font){
super.setFont(font);
if(label!=null)
label.setFont(font);
}
/**
* Override the set text method
*/
@Override
public void setText(String t){
super.setText(t);
if(label!=null)
label.setText(t);
}
/**
* Paint the button
*/
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
Graphics2D g2 = (Graphics2D)g;
g2.clearRect(0,0,width,height);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//Check Button Model state
if(model.isPressed())
paintPressedButton(g2,width,height);
else{
if(model.isRollover()){
if(fadeUp){
fadeUp = false;
timer.start();
}
}
else{
if(fadeDown){
fadeDown = false;
timer.start();
}
}
g2.setPaint(new Color(background[0],background[1],background[2],background[3]));
g2.fillRoundRect(0,0,width-1,height-1,height,height);
}
}
/**
* Draw a pressed button
*/
private void paintPressedButton(Graphics2D g2,int width,int height){
float[] temp = new float[4];
for(int i=0;i<background.length;i++)
temp[i] = background[i]-.4f < 0f ? 0f : background[i]-.4f;
g2.setPaint(new Color(temp[0],temp[1],temp[2],temp[3]));
g2.fillRoundRect(0,0,width-1,height-1,height,height);
}
/**
* paint the border
*/
public void paintBorder(Graphics g){
int width = getWidth();
int height = getHeight();
g.setColor(Color.BLACK);
g.drawRoundRect(0,0,width-1,height-1,height,height);
}
/**
* Inner action listener class
*/
private class TimerAction implements ActionListener{
private float alphaInc = .2f;
WButton button;
public TimerAction(WButton b){
button = b;
}
public void actionPerformed(ActionEvent e){
if(model.isRollover()){
background[3] += alphaInc;
if(background[3] > 1.0f){
timer.stop();
background[3] = 1.0f;
fadeDown = true;
}
}
else{
background[3] -= alphaInc;
if(background[3] < 0f){
timer.stop();
background[3] = 0f;
fadeUp = true;
}
}
button.repaint();
}
}
}
EDIT 1
What aly suggested got me closer, but not quite there. Instead of g2.clearRect() I painted the object with a transparent color as suggested. The white box is gone, but a different color is there. Upon investigation is is the color of the parent panel but with no transparency. Here are pictures for an example (the panel has 70% transparency). The first pictures is when the program starts. The second picture is after 1 mouse rollover.
What you could do is instead of using clearRect()
, clear the background with a completely transparent color.
g2.setColor(new Color(0,0,0,0));
g2.drawRect(0,0,width,height);
You still need to setOpaque(false)
on the JButton
so that it doesn't use the blue rollover color as the background once you hover over it once.
Edit: After seeing what you just posted, I think the problem is that the main frame isn't repainted.
Try:
SwingUtilities.getWindowAncestor(this).repaint();
in the paint method to repaint the frame, that might fix the problem.