Java 为什么BuffereImage输出看起来与Linux平台上JFrame窗口中的屏幕不同?
我正在从事一个项目,该项目需要捕获屏幕GUI(例如JFrame)的图像数据。不知何故,我的应用程序适用于windows和Mac操作系统,但对于Linux,它不能提供与屏幕GUI相同的图像输出Java 为什么BuffereImage输出看起来与Linux平台上JFrame窗口中的屏幕不同?,java,linux,swing,jframe,bufferedimage,Java,Linux,Swing,Jframe,Bufferedimage,我正在从事一个项目,该项目需要捕获屏幕GUI(例如JFrame)的图像数据。不知何故,我的应用程序适用于windows和Mac操作系统,但对于Linux,它不能提供与屏幕GUI相同的图像输出 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.image.BufferedImage; import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.image.BufferedImage;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.io.File;
class jframeExample {
public static BufferedImage getImageData(
Component component) {
BufferedImage image = new BufferedImage(
component.getWidth(),
component.getHeight(),
BufferedImage.TYPE_INT_RGB
);
component.printAll( image.createGraphics() );
return image;
}
public static void main(String[] args){
Runnable r = new Runnable() {
public void run() {
final JFrame f = new JFrame("JFrame Border");
f.setLayout(new BorderLayout());
f.setLocation(500,300);
f.setSize(560, 420);
f.getContentPane().setBackground(Color.BLUE);
JMenuItem screenshot =
new JMenuItem("TakeSnapshot");
screenshot.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae) {
BufferedImage imageOutput = getImageData(f);
try {
// write the image as a PNG
ImageIO.write(
imageOutput,
"png",
new File("CapturedImage.png"));
} catch(Exception e) {
e.printStackTrace();
}
}
} );
JMenu menu = new JMenu("Menu");
menu.add(screenshot);
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
f.setJMenuBar(menuBar);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
上面的代码将为GUI提供菜单选项,以将其捕获为图像输出。你们可以看到屏幕上的图形用户界面和它的图像输出作为附件。生成的图像和屏幕上的图形用户界面并没有什么不同。请参见JFrame边框的左/右边缘,它与contentPane蓝色重叠
如何获得与屏幕GUI完全相同的图像,或调整左/右边框,使其不与contentPane区域重叠?我使用LookAndFeel类尝试了几个选项,但还没有获得任何成功。如有任何帮助/建议,将不胜感激
Swing不会绘制整个框架。框架是操作系统的一个小部件 尝试使用 当帧被指定为组件时,它将使用
Robot
类拍摄图像。否则将使用Swing喷漆。快速修复
尝试改变
BufferedImage imageOutput = getImageData(f);
到
这可能也适用于Linux(我目前无法测试它),并且可以很容易地解决您的问题。
解决方案 或者,您可以使用
机器人
类Robot
具有更兼容的屏幕捕获功能,但这意味着对代码进行了严重修改。你可以在我答案的最下面找到密码。让我解释一下所有变化的原因。。。
Robot
是执行屏幕捕获所需的类。它可以捕获整个桌面或屏幕的一部分。在本例中,我们将让它通过查找桌面上相应的XY坐标来捕获应用程序的蓝色部分<代码>机器人在这种情况下需要是静态的,因为您正试图通过main()
方法访问它。因此,Robot
变量需要位于main()
方法之外,以便JMenuItem
的ActionListener
可以访问它。
newthread(()->{/*dosomething*/}.start();
getLocationOnScreen()
,位于框架的上下文窗格上(或者您希望捕获的组件)。
Robot
创建,并使用以前的代码保存到文件中代码
我想要输出完整的GUI,而不仅仅是JFrame的内容。它应该有边框、标题栏和所有内容。我对使用Robot.createScreenCapture()有点怀疑方法读取屏幕像素时,它解决了上面的示例,但如果我想通过不与当前GUI交互来捕获图像,并且假设JFrame窗口GUI上有其他GUI窗口,那么捕获的图像将不仅仅是JFrame GUI,它将只是屏幕上的矩形部分,无论此时显示什么已报告为错误:
BufferedImage imageOutput = getImageData(f.getContentPane());
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.io.File;
class jframeExample {
public static BufferedImage getImageData(
Component component) {
BufferedImage image = new BufferedImage(
component.getWidth(),
component.getHeight(),
BufferedImage.TYPE_INT_RGB
);
component.printAll( image.createGraphics() );
return image;
}
static Robot robot = null;
public static void main(String[] args){
Runnable r = new Runnable() {
public void run() {
try {
if(robot == null) robot = new Robot();
} catch (AWTException e1) {
e1.printStackTrace();
}
final JFrame f = new JFrame("JFrame Border");
f.setLayout(new BorderLayout());
f.setLocation(500,300);
f.setSize(560, 420);
f.getContentPane().setBackground(Color.BLUE);
JMenuItem screenshot =
new JMenuItem("TakeSnapshot");
screenshot.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae) {
new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
int screenshotX = f.getContentPane().getLocationOnScreen().x;
int screenshotY = f.getContentPane().getLocationOnScreen().y;
int screenshotWidth = f.getContentPane().getWidth();
int screenshotHeight = f.getContentPane().getHeight();
BufferedImage imageOutput = robot.createScreenCapture(new Rectangle(screenshotX, screenshotY, screenshotWidth, screenshotHeight));
try {
// write the image as a PNG
ImageIO.write(
imageOutput,
"png",
new File("CapturedImage.png"));
} catch(Exception e) {
e.printStackTrace();
}
}).start();
}
} );
JMenu menu = new JMenu("Menu");
menu.add(screenshot);
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
f.setJMenuBar(menuBar);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}