以某种方式可以将GUI呈现给BufferedImage或其他类型的内存图像而不在屏幕上显示它吗?
我知道这会消除各种硬件加速,但对于一个只刷新一次或两次的简单GUI,这应该不是问题。
已经尝试让JavaFX输出图像,但我找不到先在屏幕上省略渲染的方法。有没有人知道用JavaFX或Swing做到这一点的方法?
使用简单的图像处理自己绘制一个简单的GUI是没有问题的,但是我必须手动完成所有操作并使用Swing或FX会更容易。
编辑: 为了使它更清晰,我没有活动显示,但我可以保存图像,然后通过其他方式显示。确切地说,它是一个覆盆子pi,但没有使用GPIO端口连接tft显示器的主显示设备。所以我无法将UI直接渲染到显示设备,但需要创建一个我可以保存在特定位置的图像。到目前为止,我尝试的所有方法都需要主显示设备。
答案 0 :(得分:3)
是的,可以在屏幕外为图像渲染GUI。
以下是使用JavaFX的示例,示例图像输出如下:
该示例的工作原理是将图表渲染到未添加到任何窗口的场景,并且不会显示任何窗口(JavaFX术语中的舞台)。 snapshot方法用于获取节点的快照,然后使用ImageIO实用程序将快照保存到磁盘。
如果底层硬件/软件平台支持,屏幕外场景的渲染将是硬件加速的。
import javafx.application.*;
import javafx.collections.*;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.*;
import javafx.scene.chart.PieChart;
import javafx.scene.image.Image;
import javafx.scene.layout.Region;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.*;
public class OffscreenImageRecorder extends Application {
private static final Logger logger = Logger.getLogger(OffscreenImageRecorder.class.getName());
private static final String IMAGE_TYPE = "png";
private static final String IMAGE_FILENAME = "image." + IMAGE_TYPE;
private static final String WORKING_DIR = System.getProperty("user.dir");
private static final String IMAGE_PATH = new File(WORKING_DIR, IMAGE_FILENAME).getPath();
private final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
private final Random random = new Random();
private final int CHART_SIZE = 400;
@Override
public void start(Stage stage) throws IOException {
Parent chart = createChart();
Image image = snapshot(chart);
exportPng(SwingFXUtils.fromFXImage(image, null), IMAGE_PATH);
Platform.exit();
}
private Parent createChart() {
// create a chart.
final PieChart chart = new PieChart();
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Grapefruit", random.nextInt(30)),
new PieChart.Data("Oranges", random.nextInt(30)),
new PieChart.Data("Plums", random.nextInt(30)),
new PieChart.Data("Pears", random.nextInt(30)),
new PieChart.Data("Apples", random.nextInt(30))
);
chart.setData(pieChartData);
chart.setTitle("Imported Fruits - " + dateFormat.format(new Date()));
// It is important for snapshots that the chart is not animated
// otherwise we could get a snapshot of the chart before the
// data display has been animated in.
chart.setAnimated(false);
chart.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
chart.setPrefSize(CHART_SIZE, CHART_SIZE);
chart.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
return chart;
}
private Image snapshot(final Parent sourceNode) {
// Note: if the source node is not in a scene, css styles will not
// be applied during a snapshot which may result in incorrect rendering.
final Scene snapshotScene = new Scene(sourceNode);
return sourceNode.snapshot(
new SnapshotParameters(),
null
);
}
private void exportPng(BufferedImage image, String filename) {
try {
ImageIO.write(image, IMAGE_TYPE, new File(filename));
logger.log(Level.INFO, "Wrote image to: " + filename);
} catch (IOException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
launch(args);
}
}
答案 1 :(得分:0)
这有点像黑客,但您可以创建一个框架并将其放置在一个不可见的位置(在本例中使用Swing):
frame = new JFrame("Invisible frame");
frame.setBounds(-1000, 100, 640, 480);