Aqui vai um exemplo:
public class TesteEspectro extends JFrame {
public TesteEspectro() {
this.setSize(800, 600);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
this.add(new EspectroPanel(), BorderLayout.CENTER);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable()
{
@Override
public void run() {
new TesteEspectro().setVisible(true);
}
});
}
}
package espectro;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.JPanel;
public class EspectroPanel extends JPanel {
private static final int FACTOR = 5;
private void drawPoint(Graphics2D g2d, int x, int y, int a, int b, int c) {
double prop = (255.0 - y) / 255;
g2d.setColor(new Color((int) (a * prop), (int) (b * prop),
(int) (c * prop)));
g2d.drawLine(x, y, x + FACTOR, y);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setTransform(AffineTransform.getScaleInstance(getWidth()/1530.0, getHeight()/255.0));
for (int line = 0; line < 255; line++) {
for (int z = 0, x = 0; z < 255/FACTOR; z++, x=FACTOR*z) {
// Aumenta o verde
drawPoint(g2d, x, line, 255, x, 0);
// Mantém o verde, diminui o vermelho
drawPoint(g2d, x + 255, line, 255 - x, 255, 0);
// Passa a subir o azul
drawPoint(g2d, x + 510, line, 0, 255, x);
// Diminui do verde
drawPoint(g2d, x + 765, line, 0, 255 - x, 255);
// Aumenta o vermelho
drawPoint(g2d, x + 1020, line, x, 0, 255);
// Diminui o azul
drawPoint(g2d, x + 1275, line, 255, 0, 255 - x);
}
}
g2d.dispose();
}
}
Esse algoritmo não incrementa de 1 em 1, mas de FACTOR em FACTOR. Isso permite que ele atue mais rapidamente. Um fator pequeno, como 5, dificilmente será perceptível ao olho humano. Um fator grande (como 25) pode ser usado para gerar "faixas de cor", um efeito típico de desenhos animados (procure por pixel shading para mais informações).
O transform no início serve para pedir para o Java fazer a escala do tamanho do espectro (1530x255) para o tamanho do painel. Assim o espectro ocupa o painel inteiro. O ideal mesmo seria alterar o algoritmo para desenhar apenas o número de pixels na área do painel, e então calcular a posição e cor do pixel proporcionalmente. Assim, um painel pequeno passaria a consumir muito pouco processamento.
Da forma que está, sempre desenhamos 1530x255/FACTOR pixels, independente do tamanho do painel.