Tristan said:
Here is a snippet of my procedure, that does a fade in for a text:
private void fadeColor(Color pOldColor, Color pNewColor) {
int oldRed = pOldColor.getRed();
int oldGreen = pOldColor.getGreen();
int oldBlue = pOldColor.getBlue();
int newRed = pNewColor.getRed();
int newGreen = pNewColor.getGreen();
int newBlue = pNewColor.getBlue();
while ((oldRed != newRed) || (oldGreen != newGreen) || (oldBlue != newBlue)) {
if (oldRed > newRed) {
oldRed--;
} else if (oldRed < newRed) {
oldRed++;
}
if (oldGreen > newGreen) {
oldGreen--;
} else if (oldGreen < newGreen) {
oldGreen++;
}
if (oldBlue > newBlue) {
oldBlue--;
} else if (oldBlue < newBlue) {
oldBlue++;
}
color = new Color(oldRed, oldGreen, oldBlue);
// repaint container
card.repaint();
try {
sleep(20);
} catch (InterruptedException ie) {};
}
}
In this particular case, your fade is somewhat broken. I'm sure it
works (in conjunction with other code) but it goes in extremely small
steps. A fade from pure white to pure black would require 255
iterations and take an absolute minimum of 5.1 seconds. The fade can
also be uneven -- it will not take a linear path from one color to the
other for most starting and ending colors. That's because it takes
steps of the same size for each color component, even though more steps
are likely to be required overall for the different components.
A better strategy is to choose the number of steps to use for fading and
the time per step, then make it happen. Here is part of an
implementation of that approach:
private final static int FADE_STEPS = 16;
private final static int FADE_DELAY = 20;
private void fadeColor(Color oldColor, Color newColor) {
int oldRed = oldColor.getRed();
int oldGreen = oldColor.getGreen();
int oldBlue = oldColor.getBlue();
int diffRed = newColor.getRed() - oldRed;
int diffGreen = newColor.getGreen() - oldGreen;
int diffBlue = newColor.getBlue() - oldBlue;
for (int i = 1; i <= FADE_STEPS; i--) {
Color fadeColor = new Color(
oldRed + (diffRed * i) / FADE_STEPS,
oldGreen + (diffGreen * i) / FADE_STEPS,
oldBlue + (diffBlue * i) / FADE_STEPS);
repaintWithNewColor(fadeColor);
Thread.sleep(FADE_DELAY);
}
}
That's shorter and cleaner, takes a linear path through color space, and
operates in a (more or less) constant time of about one third of a
second. The smoothness and duration of the fade can be adjusted by
varying the FADE_STEPS and FADE_DELAY variables, and if you wanted
different settings for different fades then these could be turned into
parameters to the fadeColor method.
Do note, though, that neither this method nor your version should be
invoked from the event dispatch thread unless it is acceptable for the
GUI to be otherwise frozen while the fade takes place. If you want the
fade to happen concurrently with other GUI activity then you would want
to look into one of the two Timer classes. Probably javax.swing.Timer
would be best if you are already using Swing or are willing to introduce
a dependency on Swing. It gets more complicated otherwise, but should
still be doable.
John Bollinger
(e-mail address removed)