Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
To capture a JTextPane region, first choose what “screenshot” means. For an image of the Swing component itself, paint the pane into an offscreen BufferedImage, clip to the requested rectangle, and translate the graphics origin. For the pixels currently visible on a monitor, use Robot.createScreenCapture with a screen-coordinate rectangle. The two methods differ when the pane is covered, partly off-screen, or surrounded by window decorations.
Choose component rendering or desktop capture
| Requirement | Use | Coordinates | Important limitation |
|---|---|---|---|
| Capture the pane’s rendered content regardless of desktop occlusion | Offscreen BufferedImage plus paint or printAll |
JTextPane-local |
Does not include sibling components, window borders, or desktop overlays |
| Capture exactly what is visible on the monitor | Robot.createScreenCapture |
Screen coordinates | Requires desktop capture permission and includes occlusion |
| Select a region by character or document offsets | modelToView2D, followed by either method |
Document model to view, then local or screen | The pane must have a positive size and offsets must be valid |
Component painting is normally the right choice for reports, tests, exports, and automated documentation. Use Robot only when desktop composition itself is the subject.
Capture a JTextPane region by painting it off-screen
Complete Java example
This example captures a component-local rectangle and writes a PNG file. The crop’s top-left point is (x, y) in the pane’s coordinate system.
import javax.imageio.ImageIO;
import javax.swing.JTextPane;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public final class JTextPaneCapture {
public static void captureRegion(JTextPane textPane,
Rectangle crop,
File output) throws IOException {
if (crop.width <= 0 || crop.height <= 0) {
throw new IllegalArgumentException("Crop dimensions must be positive");
}
if (textPane.getWidth() <= 0 || textPane.getHeight() <= 0) {
throw new IllegalStateException("JTextPane must be laid out and sized first");
}
BufferedImage image = new BufferedImage(
crop.width, crop.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
try {
g.setClip(0, 0, crop.width, crop.height);
g.translate(-crop.x, -crop.y);
textPane.printAll(g); // Use textPane.paint(g) for normal painting.
} finally {
g.dispose();
}
if (!ImageIO.write(image, "png", output)) {
throw new IOException("No PNG image writer is available");
}
}
}
The destination image is only the crop size. Translation makes destination coordinate (0, 0) correspond to source coordinate (crop.x, crop.y); clipping prevents drawing outside the destination.
paint versus printAll
paint follows the component’s normal painting path. printAll invokes the component’s print operation and disables double buffering during that operation. For a static export, printAll often gives more deterministic output; use paint when you specifically need normal on-screen rendering behavior. Neither method captures a parent window, sibling overlay, or operating-system decoration. If those are part of the target, paint the appropriate parent or use a desktop capture.
Make layout and bounds valid first
A newly constructed pane may report zero width and height until it has been placed in a container and laid out. Call the capture after the enclosing window has been laid out, or size and validate the component explicitly in an off-screen export workflow. Verify that the crop is inside the intended component dimensions. A positive crop rectangle is required; decide separately whether out-of-bounds requests should be rejected or intersected with the pane’s bounds.
Capture a document range instead of fixed pixels
If the user selects text or you know character offsets, convert those model positions to view geometry with modelToView2D(int). The method can return null before the component has a usable size, and an invalid offset raises BadLocationException.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #2
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import java.awt.geom.Rectangle2D;
static Rectangle2D rangeStartBounds(JTextPane pane, int offset)
throws BadLocationException {
Rectangle2D bounds = pane.modelToView2D(offset);
if (bounds == null) {
throw new IllegalStateException("Pane has not been sized or laid out");
}
return bounds;
}
For a multi-line range, the start and end rectangles describe only the endpoints. Build a crop that covers every visual line in between, or iterate through the model-to-view results for the range and union the returned rectangles. Add any padding you need, then pass the resulting component-local rectangle to the off-screen capture method.
Document coordinates and view coordinates are not interchangeable: a character offset is not a pixel position. Recalculate geometry after edits, font changes, wrapping changes, or layout changes.
Capture the actual visible screen with Robot
Complete example
Robot expects screen coordinates, not coordinates relative to the pane. Convert the pane’s location to screen space, then create the capture rectangle.
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
public final class ScreenCapture {
public static void capturePaneScreenRegion(JTextPane pane,
Rectangle localCrop,
File output)
throws Exception {
if (localCrop.width <= 0 || localCrop.height <= 0) {
throw new IllegalArgumentException("Crop dimensions must be positive");
}
if (pane.getWidth() <= 0 || pane.getHeight() <= 0) {
throw new IllegalStateException("Pane must be visible and sized");
}
Point screenOrigin = new Point(0, 0);
SwingUtilities.convertPointToScreen(screenOrigin, pane);
Rectangle screenRect = new Rectangle(
screenOrigin.x + localCrop.x,
screenOrigin.y + localCrop.y,
localCrop.width,
localCrop.height);
BufferedImage image = new Robot().createScreenCapture(screenRect);
if (!ImageIO.write(image, "png", output)) {
throw new IOException("No PNG image writer is available");
}
}
}
The API describes this operation as creating an image containing “pixels read from the screen.” Consequently, another window covering the pane, a tooltip, a taskbar, scaling behavior, and other desktop composition can affect the result. Capture permissions may cause a SecurityException or undefined contents, depending on the environment.
Free tools Windows power users keep installed
One-click scans. No signup required.
Capture only the pane’s currently visible rectangle
getVisibleRect() returns the intersection of the pane’s bounds and the visible areas of its ancestors. Convert that rectangle’s origin to screen coordinates before calling Robot:
Rectangle visible = pane.getVisibleRect();
Point p = new Point(visible.x, visible.y);
SwingUtilities.convertPointToScreen(p, pane);
Rectangle screenRect = new Rectangle(p.x, p.y,
visible.width, visible.height);
BufferedImage image = new Robot().createScreenCapture(screenRect);
This captures only what is visible through scroll panes and parent clipping. It does not reveal text scrolled out of view.
Rank #4
Threading, HiDPI, and rendering details
Keep long capture work off the event dispatch thread
Painting Swing components must respect Swing’s single-thread rule, but a screen capture can be a potentially lengthy operation. Do not block the event dispatch thread while waiting for a desktop capture or writing a large image. Coordinate the component state on the EDT, then perform expensive encoding and file I/O on a worker thread; if using Robot, avoid invoking the capture in an EDT action that must keep the interface responsive.
Account for scaling and look and feel
Rendered output can vary with Java version, platform, look and feel, font availability, text antialiasing, and HiDPI scale. Component painting and screen capture may therefore have different pixel dimensions for what appears to be the same logical rectangle. Validate crop bounds and expected dimensions on each target platform. If exact regression images matter, fix the runtime, fonts, look and feel, and scale settings used by the test.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Selection and caret state
The pane’s current selection, caret, focus state, and enabled state can appear in normal painting. Decide whether that is desired. Clear selection or focus before capture when producing a clean document image; use the normal state when documenting an interactive UI. The exact appearance is look-and-feel dependent.
Best Value
Common failures and fixes
- Blank or zero-size image: the pane was never laid out. Capture after layout, or assign a positive size and validate the hierarchy.
modelToView2Dreturnsnull: the component lacks a positive usable size or layout. Size and lay out the pane before mapping offsets.BadLocationException: the document offset is outside the current document. Recompute offsets after edits and check the document length.- Wrong area captured: local and screen coordinates were mixed. Use the off-screen method with pane-local coordinates; convert to screen coordinates only for
Robot. - Covered window appears in the result: this is expected for a desktop capture. Use component painting when occlusion should not matter.
- Permission or security failure from
Robot: enable the operating system’s screen-capture permission for the Java process, or switch to off-screen component rendering. - Capture freezes the UI: move Robot capture and image encoding off the EDT while keeping Swing state changes on the EDT.
- Missing surrounding controls: painting the
JTextPanecannot include siblings or window decorations. Paint a suitable parent component or capture the desktop. - Unexpected clipping: check that the crop has positive dimensions and that its origin and extent are inside the intended component or visible rectangle.
Or skip the browser setup
If the thing you need is a screenshot of a web page rather than a local Swing component, ScreenshotNeo provides a URL-to-image or PDF API. It is not a replacement for painting a JTextPane running inside your Java desktop application, but it avoids browser automation when the target is a URL.
One GET request returns the image:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for parameters and response headers. The same request in Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up free.
Recommended Free Tools
Which method should you ship?
Use off-screen painting when the deliverable is the JTextPane rendering and it must be independent of window visibility. Use Robot when the requirement is literal monitor pixels, including occlusion and desktop composition. If the desired area is defined by text, map document offsets to view geometry first, then keep coordinate conversion explicit. That separation prevents the most common incorrect screenshots: the right rectangle in the wrong coordinate system.
Frequently Asked Questions
Can Robot capture a JTextPane that is off-screen?
Robot captures screen pixels, so an off-screen or fully covered pane cannot provide its hidden content. Paint the component into a BufferedImage instead.
Should I use paint or printAll for a PNG export?
Both are component painting paths. printAll invokes the component’s print operation with double buffering disabled; paint follows normal painting. Choose based on the rendering behavior your export requires.
Why does a document offset not match the screenshot x/y position?
Document offsets identify model text, while screenshot coordinates identify pixels. Convert offsets with modelToView2D after the pane has been sized and laid out.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

