1

I'm doing the following to a Canvas object.

graphics.setColor(BLUE);
graphics.fill(new Rectangle2D.Double(x, y, width, height));

I'd like to fade in the fill colour to create a smooth transition from the canvas background colour to the new colour (and possibly fade out whatever colour was originally there).

I've played with this kind of thing (setting the graphics object's composite to an AlphaComposite which a Timer updating the alpha value every n milliseconds) but I get flickering.

I'm wondering what general concept I'm missing.

Thanks for any pointers.

Toby
  • 9,523
  • 8
  • 36
  • 59
  • 1
    Flickering will come, mostly from, a non-double buffered source, like a `JFrame` or `JApplet`. Instead you should be ensuring that 1- You are painting to a surface which is double buffered (like anything that extends from `JComponent`) and 2- You are overriding the `paintComponent` method and calling `super.paintComponent`. Take a look at [this example](http://stackoverflow.com/questions/13203415/how-to-add-fade-fade-out-effects-to-a-jlabel/13203744#13203744) which uses `AlphaComposite` and does not suffer from flickering... – MadProgrammer Jul 30 '13 at 08:30
  • 1
    Or this [example](http://stackoverflow.com/a/2124507/230513) that varies saturation. – trashgod Jul 30 '13 at 09:11
  • `I'd like to fade in the fill colour to create a smooth transition from the canvas background colour to the new colour` - The [Fader](http://stackoverflow.com/a/16727190/131872) class does then when a component gains/loses focus. – camickr Jul 30 '13 at 15:13
  • Good tip on the `Fader` class, thanks very much – Toby Jul 31 '13 at 19:09

2 Answers2

1

First of all, how could you be using the AWT? It is quite outdated. I reccomend you switch to swing, mainly because swing has double buffering, which would remove your flicker.

tbodt
  • 16,609
  • 6
  • 58
  • 83
  • What's the Swing equivalent of Canvas? – Toby Jul 30 '13 at 09:35
  • There is no specialized drawing class like there is in the AWT, so you are supposed to use `JPanel`. A final note: **DO NOT OVERRIDE `paint`.** If you do, lots of things will not work correctly. You should override `paintComponent` instead, which is what you are supposed to do and it works. – tbodt Jul 30 '13 at 09:37
  • +1 for using Swing, `so you are supposed to use JPanel` - You would use JPanel if you need the custom painting and the component to act as a container. The more general component to use for custom painting would be `JComponent` - since it has no default functionality. – camickr Jul 30 '13 at 14:45
  • Marked as correct as you pointed out I wasn't using Swing. Swapping out to JPanel applied double buffering automatically so I'm a happy bunny again. Thanks – Toby Jul 31 '13 at 19:09
0

Your application does exactly what you tell it to do. If you want to make a fade-in effect, you have to determine what kind of color changes you want to make, create a function which does it, and implement the fade itself.

I'd approach it like that:

class FadeEffect{

  int totalDurationMs;

  int elapsedDurationMs;

  Color initialColor;

  Color finalColor;

  Color getColor(int durationDelta) {
    elapsedDurationMs += durationDelta;
    if (elapsedDurationMs > totalDurationMs) {
      return finalColor;
    }
    double progress = 1.0d*elapsedDurationMs/totalDurationMs;
    return new Color( (int)(finalColor.getRed()-initialColor.getRed())*progress,
                      (int)(finalColor.getGreen()-initialColor.getGreen())*progress,
                      (int)(finalColor.getBlue()-initialColor.getBlue())*progress);
  }

  //getters, setters, etc
}

As for the flickering issue: make sure you are using double buffering - either in your component, or by manually drawing on a off-screen buffer (image) and only posting the image to the screen when the drawing is complete.

Here is a sample code from my Graphic2D app doing the double buffering:

private VolatileImage vImg;

@Override
public void paint(Graphics g) {
    if (gc==null) gc = this.getGraphicsConfiguration();
    do {
        boolean sizeChanged = false;
        sizeChanged = (vImg!=null&&(vImg.getWidth()!=getWidth()|| vImg.getHeight()!=getHeight()));
        if (vImg == null || vImg.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE
                || sizeChanged) {
            vImg = gc.createCompatibleVolatileImage(getWidth(), getHeight());
            vImg.setAccelerationPriority(1);
        }
        final Graphics gimg =  vImg.getGraphics();
        if (gimg instanceof Graphics2D) {
            renderContents((Graphics2D) gimg);
            gimg.dispose();
            g.drawImage(vImg, 0, 0, null);
        } else {
            throw new UnsupportedOperationException("Rendering impossible, graphics are not of Graphics2D class");
        }
    } while (vImg.contentsLost());
    updateAnimationNo();
}
Dariusz
  • 21,561
  • 9
  • 74
  • 114