Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

How to capture a screenshot of the screen

Purpose. Obtain an Image with the current screen content (the OpenGL backbuffer), without repainting anything, and optionally save it. Useful for diagnostics, visual tests, and sharing.

APIs used

  • static Image Main.getScreenShot(boolean... opaque) — captures the current frame. opaque=true removes the alpha channel (makes everything opaque). It is the most common static convenience. Internally it calls the instance version on the paint thread via runOnPaintThreadAndWait.
  • Image Main.getScreenShot(boolean opaque) (instance) — same capture; schedules the read on the paint thread and blocks until it finishes.
  • Image Main.getNextScreenShot(boolean opaque) (instance) — forces a repaint and captures the next frame. Use it when you have just changed the UI and want to ensure the change shows up in the screenshot; if called off the paint thread, it repaints/updates in a loop until it gets the frame.
  • String Image.toPng(String... prefix) / String Image.toJpg(int... quality) — to save the result (see salvar-imagem.md).

Complete example (copy, paste and run)

package com.exemplo;

import dev.crossfly.*;                        // Main
import dev.crossfly.ui.*;                     // Window, Button
import dev.crossfly.ui.layout.*;             // VerticalLayout, LAY_AUTO
import dev.crossfly.ui.image.*;              // Image
import dev.crossfly.util.*;                  // Debug

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Button b = new Button("Capturar tela");
      b.onAction(origin ->
      {
         // Captures the current frame, opaque (no alpha), and saves a PNG:
         Image shot = Main.getScreenShot(true);   // true = removes alpha
         String path = shot.toPng("screen_");     // e.g.: .../screen_20260706153000.png
         Debug.log("Screenshot salvo em: " + path);

         // If you just changed the UI and want the NEXT rendered frame:
         Image next = Main.instance.getNextScreenShot(false);  // keeps alpha
      });
      add(LAY_AUTO, b);
   }
}

The snippet below shows only the core. To run it, place it inside the MainWindow skeleton above.

Minimal snippet

// verified in source: Main.java getScreenShot (533, 667) and getNextScreenShot (541)
import dev.crossfly.Main;
import dev.crossfly.ui.image.Image;

// Captures the current frame, opaque (no alpha), and saves a PNG:
Image shot = Main.getScreenShot(true);   // true = removes alpha
String path = shot.toPng("screen_");     // e.g.: .../screen_20260706153000.png

// If you just changed the UI and want the NEXT rendered frame:
Image next = Main.instance.getNextScreenShot(false);  // keeps alpha

Implementation notes (source):

  • The captured image has alreadyScreenScaled = true and undergoes flipY() (the OpenGL backbuffer comes vertically inverted).
  • On the WebGL platform, opaque=true does not apply setOpaque() (explicit guard in the code); the alpha is kept even when opaque is requested.
  • getScreenShot differs from Component.toImage(): here there is no painting/render — the backbuffer of the current frame is captured.
  • For cross-platform comparisons (e.g., tests), fix the font with Styles.setDefaultFont(Font.getFont(false, 20)), since font rendering varies per device.

Dive deeper

Was this page helpful?