Das Vorgehen dabei schaut so aus:
- erzeuge ein Int-Array in der gewünschten Größe der Zeichenfläche. In diesem Array stehen die RGB-Werte für jeden einzelnen Pixel
- erzeuge auf die oben beschriebene Weise ein BufferedImage. Das Image kann dann in die GUI eingebunden werden und interessiert eigentlich nicht weiter.
- nun kann man jederzeit nach Herzenslust RGB-Werte in das Array schreiben. Wann immer das zugehörige BufferedImage von der GUI neu gezeichnet wird holt es sich die Pixelwerte aus dem Array.
Beispiel:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Lavalampe extends TimerTask {
static final int width = 320;
static final int height = 240;
static int rgb[];
static BufferedImage image;
static JPanel panel;
static double plasmaphase = 0;
public static void main(String[] args) {
// erzeuge array fuer die rgb-werte
rgb = new int[ width * height ];
// erzeuge ein BufferedImage welches an das rgb-array gebunden ist
ColorModel colorModel = DirectColorModel.getRGBdefault();
SampleModel sampleModel = colorModel.createCompatibleSampleModel(width, height);
DataBuffer buffer = new DataBufferInt(rgb, width*height);
WritableRaster raster = Raster.createWritableRaster(sampleModel, buffer, null);
image = new BufferedImage( colorModel, raster, false, null);
// erzeuge jframe
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
panel = new JPanel() {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
};
frame.add(panel);
frame.setVisible(true);
frame.setSize(width + frame.getInsets().left + frame.getInsets().right,
height + frame.getInsets().top + frame.getInsets().bottom);
// erzeuge task der in regelmaessigen Abstaenden in das rgb-array zeichnet
Timer timer = new Timer();
timer.scheduleAtFixedRate(new Lavalampe(), 0L, 20L);
}
@Override
public void run() {
// hier wird in das rgb-array gemalt
for(int y=0; y<height; y++) {
for(int x=0; x<width; x++) {
int color = (int) ( (
Math.sin(2*Math.PI*x/width * 1.5528 - plasmaphase*0.81 )
+ Math.sin(2*Math.PI*x/width * 0.82759 + plasmaphase*0.67 )
+ Math.sin(2*Math.PI*y/height * 0.734 - plasmaphase*0.95 )
+ Math.sin(2*Math.PI*y/height * 1.2636 + plasmaphase*0.6597 )
+ 4 ) *43d);
rgb[y*width + x] = 0xff000000 | 0x800000 | (color<<16) | (color<<8);
}
}
plasmaphase+= 0.01d;
// nach dem malen ins array noch das image neu zeichnen lassen
panel.repaint();
}
}
Zeile 30: hier wird das array in der gewünschten Größe erzeugt
Zeile 33-37: das BufferedImage wird erzeugt
Zeile 42-48: das BufferedImage wird ueber ein JPanel in die GUI eingebunden. Ein Neuzeichnen des Images können wir nun mittels panel.repaint() anfordern.
Zeile 64-74: Im Timertask werden regelmäßig RGB-Werte errechnet und einfach in das Array geschrieben. Mit dem BufferedImage haben wir hier nichts mehr zu tun.
Zeile 78: die GUI wird angewiesen das Panel mit dem BufferedImage neu zu zeichnen. Da sich das BufferedImage die Pixelwerte aus unserem RGB-Array holt erscheint dieses nun auf dem Bildschirm.
PS: Ob dieses gesamte Vorgehensweise (Pixelmalen über das RGB-Array eines BufferedImages) das Prädikat „schöner Code“ verdient sei mal dahingestellt. Aber sie ist simpel und passte glaube ich ganz gut zu deiner Ausgangsfrage (so wie ich sie verstanden hatte).
PPS: Soweit ich weiss geht das nur mit eindimensionalen Arrays. Ich habe mich aber auch nicht tiefer in die Materie eingegraben, da geht bestimmt noch was.