SWT: Composite als Grafik speichern

Layna

Erfahrenes Mitglied
Hallo :).
Ich würde gerne ein SWT-Composite in eine Grafikdatei speichern, OHNE diese anzuzeigen (Anzeigen und Screenshot atimatsich machen lassne ist einfach nicht praktikabel).. war bisher leider ziemlich erfolglos.

Zum Versuchen habe ich folgendes eiegnes Compsite genommen:

Java:
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;

public class DrawIt extends Composite {
 	private Canvas canvas;

 	public DrawIt(Composite parent, int style) {
  		super(parent, style);
  		canvas = new Canvas(this, SWT.BORDER);
  		canvas.setLayout(new FillLayout());
  		canvas.addPaintListener(new PaintListener() {
   			@Override
   			public void paintControl(PaintEvent e) {
    				paint();
   			}
  		});	
 	}
 

 	private void paint(){
  		int sizeX,sizeY;
  		sizeX = canvas.getSize().x-5;
  		sizeY = canvas.getSize().y-5;
  		canvas.setBackground(new Color(this.getDisplay(),250,0,250));
  		canvas.setForeground(new Color(this.getDisplay(),250,0,250));
		
  		GC gc = new GC(canvas);
  		// Größe der nutzbaren Fläche
  		Rectangle rect = canvas.getClientArea();
  		// Puffer aufbauen
  		Image buffer = new Image(this.getDisplay(), rect.width, rect.height);
  		// Neuer Grafikkontext für Puffer
  		GC bufferGC = new GC(buffer);
  		bufferGC.setAntialias(SWT.ON);
  		bufferGC.setTextAntialias(SWT.ON);
		
  		bufferGC.setBackground(new Color(this.getDisplay(),0,0,250));
  		bufferGC.fillPolygon(new int[]{sizeX, sizeY, 0,0, sizeX,0});
  		bufferGC.setBackground(new Color(this.getDisplay(),0,250,0));
  		bufferGC.fillPolygon(new int[]{sizeX, sizeY, 0,0,0, sizeY,});
  		
  		gc.drawImage(buffer, 0, 0);
  		// Den Puffer entsorgen
  		bufferGC.dispose();
  		buffer.dispose();
  		gc.dispose();
  		
 	}
}

Das ganze wird angezeigt (erfolgreich) und soll auch als Grafik gespeichert werden (geht nicht :() in folgender Klasse:

Java:
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.beans.EventHandler;
import java.io.File;
import java.io.IOException;
import java.util.EventObject;

import javax.imageio.ImageIO;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;



public class CanvaTest {

	protected Shell shell;

	/**
	 * Launch the application
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			CanvaTest window = new CanvaTest();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window
	 */
	public void open() {
		final Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	/**
	 * Create contents of the window
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setLayout(new FormLayout());
		shell.setSize(500, 375);
		shell.setText("SWT Application");
		DrawIt dabinich = new DrawIt(shell,SWT.BORDER);
		final FormData fd_dabinich = new FormData();
		fd_dabinich.bottom = new FormAttachment(0, 150);
		fd_dabinich.top = new FormAttachment(0, 0);
		fd_dabinich.right = new FormAttachment(0, 492);
		fd_dabinich.left = new FormAttachment(0, 0);
		dabinich.setLayoutData(fd_dabinich);
		dabinich.setLayout(new FillLayout());
		
		Image img = new Image(shell.getDisplay(),400,400);
		
		GC gc = new GC(img);
		dabinich.redraw();
		dabinich.layout();
		dabinich.setSize(400, 400);
		dabinich.pack();
		boolean print = dabinich.print(gc);
		gc.drawString("Hallo", 40, 40);
		System.out.println(print);
		File f = new File("test2.jpg");
		
        BufferedImage bi = convertToAWT(img.getImageData());
        
		try {
			ImageIO.write(bi,"jpg",f);
		} catch (IOException e1) {
			// TODO Beschreibung ergänzen
			e1.printStackTrace();
		}


		final Composite composite = new Composite(shell, SWT.NONE);
		final FormData fd_composite = new FormData();
		fd_composite.bottom = new FormAttachment(0, 295);
		fd_composite.right = new FormAttachment(0, 275);
		fd_composite.top = new FormAttachment(0, 185);
		fd_composite.left = new FormAttachment(0, 30);
		composite.setLayoutData(fd_composite);
		composite.setBackgroundImage(img);
		composite.setLayout(new FormLayout());
	//
	}
	
	static BufferedImage convertToAWT(ImageData data) {
	    ColorModel colorModel = null;
	    PaletteData palette = data.palette;
	    if (palette.isDirect) {
	      colorModel = new DirectColorModel(data.depth, palette.redMask,
	          palette.greenMask, palette.blueMask);
	      BufferedImage bufferedImage = new BufferedImage(colorModel,
	          colorModel.createCompatibleWritableRaster(data.width,
	              data.height), false, null);
	      WritableRaster raster = bufferedImage.getRaster();
	      int[] pixelArray = new int[3];
	      for (int y = 0; y < data.height; y++) {
	        for (int x = 0; x < data.width; x++) {
	          int pixel = data.getPixel(x, y);
	          RGB rgb = palette.getRGB(pixel);
	          pixelArray[0] = rgb.red;
	          pixelArray[1] = rgb.green;
	          pixelArray[2] = rgb.blue;
	          raster.setPixels(x, y, 1, 1, pixelArray);
	        }
	      }
	      return bufferedImage;
	    } else {
	      RGB[] rgbs = palette.getRGBs();
	      byte[] red = new byte[rgbs.length];
	      byte[] green = new byte[rgbs.length];
	      byte[] blue = new byte[rgbs.length];
	      for (int i = 0; i < rgbs.length; i++) {
	        RGB rgb = rgbs[i];
	        red[i] = (byte) rgb.red;
	        green[i] = (byte) rgb.green;
	        blue[i] = (byte) rgb.blue;
	      }
	      if (data.transparentPixel != -1) {
	        colorModel = new IndexColorModel(data.depth, rgbs.length, red,
	            green, blue, data.transparentPixel);
	      } else {
	        colorModel = new IndexColorModel(data.depth, rgbs.length, red,
	            green, blue);
	      }
	      BufferedImage bufferedImage = new BufferedImage(colorModel,
	          colorModel.createCompatibleWritableRaster(data.width,
	              data.height), false, null);
	      WritableRaster raster = bufferedImage.getRaster();
	      int[] pixelArray = new int[1];
	      for (int y = 0; y < data.height; y++) {
	        for (int x = 0; x < data.width; x++) {
	          int pixel = data.getPixel(x, y);
	          pixelArray[0] = pixel;
	          raster.setPixel(x, y, pixelArray);
	        }
	      }
	      return bufferedImage;
	    }
	  }

}

Bisher scheint alles für mich darauf hinzudeuten, dass das Composite auf das GC gelegt wird OHNE das die Paint-Methode aufgerufen wird... was ärgerlich ist ;),
Vielelicht weiß jemand hier ja wo das Brett, das vor meinem Kopf hängt, zu zerschlagen ist :).

Layna
 
Also, erst einmal: wenn jemand nochmal vor so einem Problem steht:

Die folgende Funktion scheint (für win32) für alle SWT-Controls wunderbar zu funktionieren:

Java:
		table.redraw();
        Point tableSize = table.getSize();
        Point size = table.getSize();
        Image image = new Image(table.getDisplay(), size.x, size.y);
        GC gc = new GC(image);
        int hWnd = table.handle;
        int wParam = gc.handle;
        int lParam = OS.PRF_NONCLIENT | OS.PRF_CLIENT | OS.PRF_ERASEBKGND;
        OS.SendMessage(hWnd, OS.WM_PRINT, wParam, lParam);
        gc.dispose();
        ImageLoader imageLoader = new ImageLoader();
        imageLoader.data = new ImageData[] {image.getImageData()};
        imageLoader.save("lala.jpg",SWT.IMAGE_JPEG);

Leider weigert sich diese Version Widgets abzulichten, die von "Composite" abgeleitet sind.... hat jemand hierzu noch eine Idee?

Layna
 
Leider exakt das; das Snippet macht einen Screenshot,was nicht nur nicht das ist was ich will, sondern auch riskant falls sich während des "abfotografierens" (screenschootens..) ein anderes Fenster automatisch noch vorne schiebt. Mit dem Debugger kann man zum Beispiel wunderbar mitten drinne die Eclipse nach vorne ziehen, und hat dann einen ausschnitt der Eclipse abgelichtet... leidvolle Erfahrung die mich im ersten Moment seehr verwirrte ;).
 
Zurück