vải Vì vậy, sau khi một số nghiên cứu tôi đã thực hiện vẽ với JavaFX và đây là một ví dụ đơn giản:
Đầu tiên tôi đã ứng dụng JavaFX đang được đưa ra trong một thread riêng biệt (tôi sử dụng Spring taskExecutor nhưng một java đơn giản thread có thể được sử dụng).
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);
}
}
}
Sau đó tôi gọi là initialize() phương pháp khi ứng dụng Mùa xuân đang bắt đầu:
@Autowired private TaskExecutor taskExecutor;
@PostConstruct private void initChartGenerator() {
ChartGenerator.initialize(taskExecutor);
}
Giải pháp này của cource có thể được chuyển đến một ứng dụng không mùa xuân.
Đây là giải pháp đơn luồng (trong trường hợp của tôi là đủ) nhưng tôi nghĩ rằng nó có thể được áp dụng cho việc sử dụng đa luồng (có thể sử dụng RMI để gọi phương thức vẽ).
Ngoài ra giải pháp này làm việc "nguyên trạng" trên máy trạm cửa sổ của tôi, nhưng trên môi trường máy chủ Linux một số hành động bổ sung nên được gọi:
- Bạn không thể sử dụng JavaFX trên OpenJDK (tính đến tháng 8 năm 2013) - phải chuyển Oracle JDK
- phiên bản Java phải không ít hơn Java 7u6
Các phức tạp nhất - bạn phải sử dụng màn hình ảo để làm cho JavaFX chạy trên môi trường không đầu:
apt-get install Xvfb
// đó trở đi bắt đầu máy chủ ứng dụng:
xuất khẩu DISPLAY = ": 99"
start-stop-daemon --start --background --user cầu cảng --exec "/ usr/bin/sudo" - -u cầu cảng/usr/bin/Xvfb: 99 -screen 0 1024x768x24
PSBạn cũng có thể sử dụng các khả năng JavaFX khác trên phía máy chủ (ví dụ: xuất html sang hình ảnh) bằng giải pháp này.
Điều này thật tuyệt. Tôi rất vui khi thử nó. Cảm ơn cho những nỗ lực! – GGrec