Also nach einigen Recherchen habe ich umgesetzt Leinwand mit JavaFX ziehen und hier ist ein vereinfachtes Beispiel:
Zuerst habe ich die JavaFX Antrag gestellt, die in einem separaten Thread gestartet wird (ich benutze Frühling taskExecutor aber eine reine Java Faden kann verwendet werden).
public class ChartGenerator extends Application {
private static Canvas canvas;
private static volatile byte[] result;
public static void initialize(TaskExecutor taskExecutor) {
taskExecutor.execute(new Runnable() {
@Override
public void run() {
launch(ChartGenerator.class);
}
});
}
public static synchronized byte[] generateChart(final Object... params) {
Platform.runLater(new Runnable() {
@Override
public void run() {
ByteArrayOutputStream baos = null;
try {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
/**
* Do the work with canvas
**/
final SnapshotParameters snapshotParameters = new SnapshotParameters();
snapshotParameters.setFill(Color.TRANSPARENT);
WritableImage image = canvas.snapshot(snapshotParameters, null);
BufferedImage bImage = SwingFXUtils.fromFXImage(image, null);
baos = new ByteArrayOutputStream();
ImageIO.write(bImage, chartType.outputFormat, baos);
result = baos.toByteArray();
} catch (InstantiationException e) {
throw new ChartGenerationException(e);
} catch (IllegalAccessException e) {
throw new ChartGenerationException(e);
} catch (NoSuchMethodException e) {
throw new ChartGenerationException(e);
} catch (InvocationTargetException e) {
throw new ChartGenerationException(e);
} catch (IOException e) {
throw new ChartGenerationException(e);
} finally {
IOUtils.closeQuietly(baos);
}
}
});
while (result == null) {
//wait
}
byte[] ret = result;
result = null;
return ret;
}
@Override
public void start(Stage stage) {
canvas = new Canvas();
}
public static class ChartGenerationException extends RuntimeException {
public ChartGenerationException(String message) {
super(message);
}
public ChartGenerationException(Throwable cause) {
super(cause);
}
}
}
Dann rufe ich die initialize() -Methode, wenn der Frühling Anwendung gestartet wird:
@Autowired private TaskExecutor taskExecutor;
@PostConstruct private void initChartGenerator() {
ChartGenerator.initialize(taskExecutor);
}
Diese Lösung von cource kann auf eine nicht-Spring-Anwendung portiert werden.
Dies ist eine single-threaded-Lösung (in meinem Fall ist es genug), aber ich denke, es könnte zu Multithread-Nutzung angenommen werden (vielleicht RMI verwenden, um Draw-Methode aufrufen).
Auch diese Lösung funktioniert „as is“ auf meinem Windows-Workstation aber auf Linux-Server-Umgebung einige zusätzliche Aktionen aufgerufen werden soll:
- Sie nicht JavaFX auf OpenJDK verwenden können (Stand: August 2013) - haben zu wechseln Oracle JDK muss
- Java-Version nicht weniger als Java 7u6
Die komplexeste - Sie virtuelle Anzeige zu machen JavaFX laufen auf headless-Umgebungen verwenden:
apt-get install xvfb
// dann auf Anwendungsserver Start:
export DISPLAY = "99"
Start-Stopp-Daemon --start --background --user Anlegesteg --exec „/ usr/bin/sudo“- -u Anlegesteg/usr/bin/Xvfb: 99 -Bildschirm 0 1024x768x24
PSSie können mit dieser Lösung auch andere JavaFX-Funktionen auf Serverseite verwenden (z. B. HTML in Image exportieren).
Das ist cool. Ich bin so aufgeregt, es auszuprobieren. Danke für die Bemühung! – GGrec