有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java渲染GUI到内存中的图像

是否有可能将GUI呈现给BuffereImage或其他类型的内存映像而不在屏幕上显示

我知道这会降低各种硬件加速,但对于一个每秒只刷新一到两次的简单GUI来说,这应该不是问题

已经尝试让JavaFX输出图像,但我找不到一种方法可以先在屏幕上省去渲染。有人知道用JavaFX或Swing实现这一点的方法吗

使用简单的图像处理自己绘制一个简单的GUI是没有问题的,但是我必须手工完成,使用Swing或FX将使它变得更容易

编辑: 为了让它更清楚一点,我没有一个活动的显示器,但我可以保存一个图像,然后通过其他方式显示。确切地说,它是一个raspberry pi,但没有一个主显示设备,使用GPIO端口连接tft显示器。因此,我无法将UI直接呈现给显示设备,但需要创建一个可以保存在特定位置的图像。到目前为止,我尝试的所有方法都需要一个主显示设备


共 (2) 个答案

  1. # 1 楼答案

    是的,可以将GUI呈现到屏幕外的图像

    下面是一个使用JavaFX的示例,图像输出示例如下:

    image

    该示例的工作原理是将图表渲染到一个场景中,该场景没有添加到任何窗口,也没有显示任何窗口(JavaFX术语中的Stage)。使用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);
        }
    }
    
  2. # 2 楼答案

    这有点像黑客,但您可以创建一个框架并将其放置在一个不可见的位置(在本例中使用Swing):

    frame = new JFrame("Invisible frame");
    frame.setBounds(-1000, 100, 640, 480);