最近公司的用例执行需要截图,而且要求比较详细,一个case执行下来动不动十几张,二十张甚至三四十张图片,平时都是截完一张就贴到word文档中,一个case执行完了就把所有的截图整理好放在一个word文档下,既拖累了用例执行速度,操作起来又很麻烦。这里用Java实现了一个截屏的功能,并且自动把截取的图片按照用户设定好的路径和case名字存到对应的文件夹下,case执行完成之后手动点击合成,就可以将一个执行一个case所截的图片按先后顺序合成为一张图片,能提升效率。同时截图除了支持手动点击截图外,还支持快捷键截屏(Ctrl+K),支持快捷键显示弹框和隐藏弹框(Ctrl+H),由于Java原生不支持全局的键盘时间监听,这里引入了第三方JIntellitype包来实现,JIntellitype最好用1.4.1版本的
<dependency>
<groupId>com.melloware</groupId>
<artifactId>jintellitype</artifactId>
<version>1.4.1</version>
</dependency>
最后实现的效果如下:
文件路径是截屏后图片保存的路径,用例编号是标识截的图片关联哪个用例的如
路径填写:C:\Program Files\Java\AWT
用例编号填写:case1653
那么截屏成功后的图片就保存在 C:\Program Files\Java\AWT\case1653下,合成的图片也在这里
import com.melloware.jintellitype.JIntellitype;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SuperCaptureTool {
private JFrame frame;
private Robot robot;
private JTextField pathTextField;
private JTextField filenameTextField;
private JButton countButton;
private String savePath;
private int screenshotCount = 0;
public static final JIntellitype instance = JIntellitype.getInstance();
public SuperCaptureTool(String savePath) throws AWTException {
this.robot = new Robot();
this.savePath = savePath;
createWindow();
}
private void createWindow() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(320, 150);
frame.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.insets = new Insets(3, 3, 3, 3);
// 文件路径标题
JLabel pathLabel = new JLabel("文件路径:");
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1;
constraints.anchor = GridBagConstraints.CENTER;
frame.add(pathLabel, constraints);
// 文件路径输入框
pathTextField = new JTextField(20);
constraints.gridx = 1;
constraints.gridy = 0;
constraints.weightx = 2;
pathTextField.setText(savePath);
frame.add(pathTextField, constraints);
// 用例编号标题
JLabel filenameLabel = new JLabel("用例编号:");
constraints.gridx = 0;
constraints.gridy = 1;
constraints.weightx = 1;
frame.add(filenameLabel, constraints);
// 用例编号输入框
filenameTextField = new JTextField(20);
constraints.gridx = 1;
constraints.gridy = 1;
constraints.weightx = 2;
frame.add(filenameTextField, constraints);
// 序号展示按钮
countButton = new JButton();
this.countButton.setText("序号: " + screenshotCount);
constraints.gridx = 2;
constraints.gridy = 0;
constraints.weightx = 0.5;
frame.add(this.countButton, constraints);
JButton captureButton = new JButton("截屏");
constraints.gridx = 1;
constraints.gridy = 2;
constraints.weightx = 2;
frame.add(captureButton, constraints);
JButton mergeButton = new JButton("合成");
constraints.gridx = 2;
constraints.gridy = 1;
constraints.weightx = 0.5;
frame.add(mergeButton, constraints);
JButton resetButton = new JButton("重置");
constraints.gridx = 0;
constraints.gridy = 2;
constraints.weightx = 1;
frame.add(resetButton, constraints);
frame.setVisible(true);
captureButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
captureScreen(false);
}
});
mergeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mergeScreenshots();
}
});
resetButton.addActionListener(e -> {
this.screenshotCount = 0;
this.countButton.setText("序号: " + this.screenshotCount);
});
instance.registerHotKey(75, JIntellitype.MOD_CONTROL, (int) 'K');
instance.registerHotKey(72, JIntellitype.MOD_CONTROL, (int) 'H');
// 添加热键监听器
instance.addHotKeyListener((hotKeyID) -> {
if (hotKeyID == 75) { // Ctrl+K热键被触发
try {
captureScreen(true);
} catch (Exception e) {
e.printStackTrace();
}
} else if (hotKeyID == 72) {
boolean visible = frame.isVisible();
frame.setVisible(!visible);
}
});
}
public static void main(String[] args) {
int targetWidth = 0;
int targetHeight = 0;
String path = "D:\\caseimages";
try {
SuperCaptureTool tool = new SuperCaptureTool(path);
} catch (AWTException e) {
throw new RuntimeException(e);
}
}
private void captureScreen(boolean isKeyEvent) {
String inputPath = pathTextField.getText().trim();
if (!inputPath.isEmpty()) {
this.savePath = inputPath;
}
File savePath = new File(this.savePath);
if (!savePath.isDirectory()) {
return;
}
String filename = filenameTextField.getText().trim();
if (filename.isEmpty()) {
return;
}
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRect = new Rectangle(screenSize);
BufferedImage capture = robot.createScreenCapture(screenRect);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm");
String timestamp = dateFormat.format(new Date());
String fullFilename = filename + "-" + timestamp + "-" + screenshotCount + ".png";
String path = savePath + File.separator + filenameTextField.getText().trim();
File f = new File(path);
if (!f.exists()) {
f.mkdir();
}
File outputFile = new File(path, fullFilename);
screenshotCount++;
this.countButton.setText("序号: " + screenshotCount);
try {
ImageIO.write(capture, "png", outputFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (isKeyEvent) {
frame.setVisible(!frame.isVisible());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
frame.setVisible(!frame.isVisible());
}
}
void mergeImages(String folderPath, String outputImagePath, int targetWidth, int targetHeight) {
try {
File folder = new File(folderPath);
File[] files = folder.listFiles();
if (targetWidth == 0 || targetHeight == 0) {
for (File file : files) {
BufferedImage image = ImageIO.read(file);
if (targetWidth < image.getWidth()) {
targetWidth = image.getWidth();
}
targetHeight += image.getHeight();
}
}
BufferedImage mergedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = mergedImage.createGraphics();
int y = 0;
for (File file : files) {
BufferedImage image = ImageIO.read(file);
g2d.drawImage(image, 0, y, null);
y += image.getHeight();
}
g2d.dispose();
File outputFile = new File(outputImagePath);
boolean png = ImageIO.write(mergedImage, "png", outputFile);
} catch (IOException e) {
e.printStackTrace();
}
}
private void mergeScreenshots() {
String path = savePath + File.separator + filenameTextField.getText().trim();
File f = new File(path);
if (!f.exists()) {
f.mkdir();
}
File folder = new File(path);
if (!folder.exists() || !folder.isDirectory()) {
return;
}
File[] files = folder.listFiles();
if (files.length == 0) {
return;
}
int targetWidth = 0;
int targetHeight = 0;
for (File file : files) {
if (file.getName().contains("merged")) {
continue;
}
BufferedImage image;
try {
image = ImageIO.read(file);
if (image != null) {
targetWidth = Math.max(targetWidth, image.getWidth());
targetHeight += image.getHeight();
}
} catch (IOException e) {
e.printStackTrace();
}
}
BufferedImage mergedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = mergedImage.createGraphics();
int y = 0;
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.getName().contains("merged")) {
continue;
}
BufferedImage image;
try {
image = ImageIO.read(file);
if (image != null) {
g2d.drawImage(image, 0, y, null);
y += image.getHeight();
}
} catch (IOException e) {
e.printStackTrace();
}
}
g2d.dispose();
String filename = filenameTextField.getText().trim();
String path2 = savePath + File.separator + filename;
File f2 = new File(path2);
if (!f.exists()) {
f.mkdir();
}
String outputImagePath = f.getAbsolutePath() + File.separator + filename + "-merged" + (screenshotCount + 1) + ".png";
File outputFile = new File(outputImagePath);
try {
ImageIO.write(mergedImage, "png", outputFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
1、首先是热键的注册用法,这里JIntellitype.getInstance()是一个单例模式,然后注册了两个快捷键:Ctrl+K和Ctrl+H
JIntellitype.getInstance().registerHotKey(75, JIntellitype.MOD_CONTROL, (int) 'K');
JIntellitype.getInstance().registerHotKey(72, JIntellitype.MOD_CONTROL, (int) 'H');
2、注册热键后,就可以给快捷键绑定监听事件
instance.addHotKeyListener((hotKeyID) -> {
if (hotKeyID == 75) { // Ctrl+K热键被触发
//do Somethiing
}
if (hotKeyID == 72) { // Ctrl+H热键被触发
//do Somethiing
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。