如何判断一个JFrame的绘图状态?
How to determine the drawing state of a JFrame?
我想截图JavaJFrame
。
有时候帧渲染没有完成,但是截图操作完成了。但是有时候他不会出现这种情况,好像跟根电脑性能有一定的关系!
Situation screenshots <--- 情况截图
我觉得可以Thread.sleep()
延迟截图,但是无法确定sleep()
的时间长度
Java代码:
package com.richardtang.apktesttool;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Test2 {
public static Robot robot;
static {
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JPanel jPanel = new JPanel();
for (int i = 1; i < 1000; i++) {
jPanel.add(new JLabel(String.valueOf(i)));
}
JFrame jFrame = new JFrame();
jFrame.setSize(500, 500);
jFrame.setContentPane(jPanel);
jFrame.setVisible(true);
BufferedImage img = captureFrame(jFrame);
try {
ImageIO.write(img, "png", new File("/tmp/1.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static BufferedImage captureFrame(JFrame window) {
window.setAlwaysOnTop(true);
Point windowPoint = window.getLocation();
Dimension windowSize = window.getSize();
Rectangle rectangle = new Rectangle(
(int) windowPoint.getX(),
(int) windowPoint.getY(),
windowSize.width,
windowSize.height
);
return robot.createScreenCapture(rectangle);
}
}
您可以使用 SwingUtilities invokeLater。根据文档,invokeLater
导致 doRun.run() 在 AWT 事件调度线程上异步执行。这将在处理完所有未决 AWT 事件后发生。因此,将在 frame/panel 绘制完成后进行屏幕截图。
更新
正如@camickr 正确指出的那样,确保您的 GUI 也以类似的方式创建,即在 AWT 事件调度线程 (EDT) 上创建。示例如下。
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ScreenCapture {
JFrame jFrame = null;
public void createGUI() {
JPanel jPanel = new JPanel();
for (int i = 1; i < 1000; i++) {
jPanel.add(new JLabel(String.valueOf(i)));
}
jFrame = new JFrame();
jFrame.setSize(500, 500);
jFrame.setContentPane(jPanel);
jFrame.setVisible(true);
}
public void capture() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
BufferedImage img = captureFrame(jFrame);
ImageIO.write(img, "png", new File("tmp/1.png"));
} catch (AWTException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public static void main(String[] args) {
ScreenCapture sc = new ScreenCapture();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
sc.createGUI();
sc.capture();
}
});
}
public static BufferedImage captureFrame(JFrame window) throws AWTException {
Robot robot = new Robot();
window.setAlwaysOnTop(true);
Point windowPoint = window.getLocation();
Dimension windowSize = window.getSize();
Rectangle rectangle = new Rectangle((int) windowPoint.getX(), (int) windowPoint.getY(), windowSize.width,
windowSize.height);
return robot.createScreenCapture(rectangle);
}
}
我想截图JavaJFrame
。
有时候帧渲染没有完成,但是截图操作完成了。但是有时候他不会出现这种情况,好像跟根电脑性能有一定的关系!
Situation screenshots <--- 情况截图
我觉得可以Thread.sleep()
延迟截图,但是无法确定sleep()
的时间长度
Java代码:
package com.richardtang.apktesttool;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Test2 {
public static Robot robot;
static {
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JPanel jPanel = new JPanel();
for (int i = 1; i < 1000; i++) {
jPanel.add(new JLabel(String.valueOf(i)));
}
JFrame jFrame = new JFrame();
jFrame.setSize(500, 500);
jFrame.setContentPane(jPanel);
jFrame.setVisible(true);
BufferedImage img = captureFrame(jFrame);
try {
ImageIO.write(img, "png", new File("/tmp/1.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static BufferedImage captureFrame(JFrame window) {
window.setAlwaysOnTop(true);
Point windowPoint = window.getLocation();
Dimension windowSize = window.getSize();
Rectangle rectangle = new Rectangle(
(int) windowPoint.getX(),
(int) windowPoint.getY(),
windowSize.width,
windowSize.height
);
return robot.createScreenCapture(rectangle);
}
}
您可以使用 SwingUtilities invokeLater。根据文档,invokeLater
导致 doRun.run() 在 AWT 事件调度线程上异步执行。这将在处理完所有未决 AWT 事件后发生。因此,将在 frame/panel 绘制完成后进行屏幕截图。
更新
正如@camickr 正确指出的那样,确保您的 GUI 也以类似的方式创建,即在 AWT 事件调度线程 (EDT) 上创建。示例如下。
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ScreenCapture {
JFrame jFrame = null;
public void createGUI() {
JPanel jPanel = new JPanel();
for (int i = 1; i < 1000; i++) {
jPanel.add(new JLabel(String.valueOf(i)));
}
jFrame = new JFrame();
jFrame.setSize(500, 500);
jFrame.setContentPane(jPanel);
jFrame.setVisible(true);
}
public void capture() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
BufferedImage img = captureFrame(jFrame);
ImageIO.write(img, "png", new File("tmp/1.png"));
} catch (AWTException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public static void main(String[] args) {
ScreenCapture sc = new ScreenCapture();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
sc.createGUI();
sc.capture();
}
});
}
public static BufferedImage captureFrame(JFrame window) throws AWTException {
Robot robot = new Robot();
window.setAlwaysOnTop(true);
Point windowPoint = window.getLocation();
Dimension windowSize = window.getSize();
Rectangle rectangle = new Rectangle((int) windowPoint.getX(), (int) windowPoint.getY(), windowSize.width,
windowSize.height);
return robot.createScreenCapture(rectangle);
}
}