|
|
package xyz.wbsite.jmacro.tool;
|
|
|
|
|
|
import cn.hutool.core.img.ImgUtil;
|
|
|
import cn.hutool.core.io.FileUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import cn.hutool.log.StaticLog;
|
|
|
import xyz.wbsite.jmacro.base.Legend;
|
|
|
import xyz.wbsite.jmacro.util.DialogUtil;
|
|
|
import xyz.wbsite.jmacro.util.Logger;
|
|
|
|
|
|
import javax.swing.*;
|
|
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
|
|
import java.awt.*;
|
|
|
import java.awt.event.KeyAdapter;
|
|
|
import java.awt.event.KeyEvent;
|
|
|
import java.awt.event.MouseAdapter;
|
|
|
import java.awt.event.MouseEvent;
|
|
|
import java.awt.event.MouseMotionAdapter;
|
|
|
import java.awt.event.WindowAdapter;
|
|
|
import java.awt.event.WindowEvent;
|
|
|
import java.awt.image.BufferedImage;
|
|
|
import java.io.File;
|
|
|
import java.util.List;
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
import java.util.prefs.Preferences;
|
|
|
|
|
|
/**
|
|
|
* 辅助截屏工具
|
|
|
*
|
|
|
* @author wangbing
|
|
|
* @version 0.0.1
|
|
|
* @since 1.8
|
|
|
*/
|
|
|
public class PickLegend extends JFrame {
|
|
|
|
|
|
private static final String LAST_PATH = "capture.last.path";
|
|
|
|
|
|
/**
|
|
|
* 参照原点x坐标
|
|
|
*/
|
|
|
private int originX;
|
|
|
/**
|
|
|
* 参照原点y坐标
|
|
|
*/
|
|
|
private int originY;
|
|
|
|
|
|
/**
|
|
|
* 全屏幕截图
|
|
|
*/
|
|
|
private BufferedImage capture;
|
|
|
|
|
|
/**
|
|
|
* 背景蒙层
|
|
|
*/
|
|
|
private final Color mask = new Color(0, 0, 0, 0.2f);
|
|
|
|
|
|
/**
|
|
|
* 聚焦框线条
|
|
|
*/
|
|
|
private final Stroke focusWindow = new BasicStroke(1.0f);
|
|
|
|
|
|
/**
|
|
|
* 屏幕截图区域起始坐标
|
|
|
*/
|
|
|
private final Point start = new Point(0, 0);
|
|
|
|
|
|
/**
|
|
|
* 屏幕截图区域结束坐标
|
|
|
*/
|
|
|
private final Point end = new Point(0, 0);
|
|
|
|
|
|
/**
|
|
|
* 个人首选项配置工具
|
|
|
*/
|
|
|
private Preferences preferences;
|
|
|
|
|
|
/**
|
|
|
* 有参照原点的构造器
|
|
|
*
|
|
|
* @param originX 原点x
|
|
|
* @param originY 原点y
|
|
|
* @throws AWTException
|
|
|
*/
|
|
|
public PickLegend(int originX, int originY, File path) throws AWTException {
|
|
|
this();
|
|
|
this.originX = originX;
|
|
|
this.originY = originY;
|
|
|
this.preferences.put(LAST_PATH, path.isDirectory() ? path.getAbsolutePath() : path.getParent());
|
|
|
}
|
|
|
|
|
|
public PickLegend() throws AWTException {
|
|
|
init();
|
|
|
}
|
|
|
|
|
|
private void init() throws AWTException {
|
|
|
setExtendedState(Frame.MAXIMIZED_BOTH);
|
|
|
setLocation(0, 0);//位置
|
|
|
setUndecorated(true);
|
|
|
setAlwaysOnTop(true);
|
|
|
setBackground(mask);
|
|
|
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
|
|
|
|
|
|
// 初始化偏好设置
|
|
|
preferences = Preferences.userRoot().node(this.getClass().getName());
|
|
|
|
|
|
// 获取屏幕截图
|
|
|
Robot robot = new Robot();
|
|
|
Toolkit tk = Toolkit.getDefaultToolkit();
|
|
|
capture = robot.createScreenCapture(new Rectangle(0, 0, tk.getScreenSize().width, tk.getScreenSize().height));
|
|
|
|
|
|
// 监听窗口关闭
|
|
|
addWindowListener(new WindowAdapter() {
|
|
|
@Override
|
|
|
public void windowClosing(WindowEvent e) {
|
|
|
// 关闭应用时要释放资源
|
|
|
dispose();
|
|
|
System.exit(0);//0正常退出,1非正常退出
|
|
|
}
|
|
|
});
|
|
|
|
|
|
addMouseListener(new MouseAdapter() {
|
|
|
@Override
|
|
|
public void mousePressed(MouseEvent e) {
|
|
|
super.mousePressed(e);
|
|
|
start.setLocation(e.getX(), e.getY());
|
|
|
end.setLocation(e.getX(), e.getY());
|
|
|
Logger.info("起始坐标:{}", start);
|
|
|
repaint();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void mouseReleased(MouseEvent e) {
|
|
|
super.mouseReleased(e);
|
|
|
end.setLocation(e.getX(), e.getY());
|
|
|
Logger.info("结束坐标:{}", end);
|
|
|
save();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
addMouseMotionListener(new MouseMotionAdapter() {
|
|
|
@Override
|
|
|
public void mouseDragged(MouseEvent e) {
|
|
|
super.mouseDragged(e);
|
|
|
end.setLocation(e.getX(), e.getY());
|
|
|
repaint();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
addKeyListener(new KeyAdapter() {
|
|
|
|
|
|
@Override
|
|
|
public void keyReleased(KeyEvent e) {
|
|
|
switch (e.getKeyCode()) {
|
|
|
case KeyEvent.VK_ESCAPE: {
|
|
|
StaticLog.info("exit.");
|
|
|
close();
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
});
|
|
|
|
|
|
setVisible(true);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void doLayout() {
|
|
|
super.doLayout();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void paint(Graphics g) {
|
|
|
super.paint(g);
|
|
|
Graphics2D g2d = (Graphics2D) g;
|
|
|
g2d.drawImage(capture, 0, 0, capture.getWidth(), capture.getHeight(), this);
|
|
|
|
|
|
// 在背景图上加个蒙层
|
|
|
g2d.setColor(mask);
|
|
|
g2d.fillRect(0, 0, capture.getWidth(), capture.getHeight());
|
|
|
|
|
|
int w = getCaptureWidth();
|
|
|
int h = getCaptureHeight();
|
|
|
if (w > 0 && h > 0) {
|
|
|
g2d.setStroke(focusWindow);
|
|
|
g2d.setColor(Color.green);
|
|
|
g2d.drawRect(getCaptureX(), getCaptureY(), w, h);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public int getCaptureX() {
|
|
|
return (int) Math.min(start.getX(), end.getX());
|
|
|
}
|
|
|
|
|
|
public int getCaptureY() {
|
|
|
return (int) Math.min(start.getY(), end.getY());
|
|
|
}
|
|
|
|
|
|
public int getCaptureWidth() {
|
|
|
return (int) Math.abs(start.getX() - end.getX());
|
|
|
}
|
|
|
|
|
|
public int getCaptureHeight() {
|
|
|
return (int) Math.abs(start.getY() - end.getY());
|
|
|
}
|
|
|
|
|
|
public void save() {
|
|
|
// 上一次保存目录
|
|
|
String lastPath = preferences.get(LAST_PATH, "");
|
|
|
// 默认文件名
|
|
|
String filename = StrUtil.format("{}.png", System.currentTimeMillis());
|
|
|
|
|
|
JFileChooser jFileChooser = new JFileChooser();
|
|
|
jFileChooser.setFileFilter(new FileNameExtensionFilter("png", "png"));
|
|
|
jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
|
|
jFileChooser.setCurrentDirectory(new File(lastPath));
|
|
|
jFileChooser.setSelectedFile(new File(filename));
|
|
|
int returnVal = jFileChooser.showSaveDialog(this);
|
|
|
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
|
|
File selectedFile = jFileChooser.getSelectedFile();
|
|
|
String legendName = selectedFile.getName();
|
|
|
if (!legendName.endsWith(".png")) {
|
|
|
legendName += ".png";
|
|
|
}
|
|
|
|
|
|
File parentDir = selectedFile.getParentFile();
|
|
|
String finalLegendName = legendName;
|
|
|
|
|
|
// 提取公共的保存逻辑
|
|
|
Runnable saveAction = () -> {
|
|
|
File targetFile = new File(parentDir, finalLegendName);
|
|
|
doSave(targetFile);
|
|
|
close();
|
|
|
};
|
|
|
|
|
|
List<File> existingFiles = FileUtil.loopFiles(Legend.getDefaultBase(),
|
|
|
pathname -> pathname.getName().equals(finalLegendName));
|
|
|
|
|
|
if (existingFiles.isEmpty()) {
|
|
|
saveAction.run();
|
|
|
} else {
|
|
|
DialogUtil.confirm("提示", "存在相同图例,是否覆盖?", result -> {
|
|
|
if (result) {
|
|
|
saveAction.run();
|
|
|
} else {
|
|
|
close(); // 用户取消时也关闭窗口
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
} else {
|
|
|
close(); // 用户取消选择时关闭窗口
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void doSave(File targetFile) {
|
|
|
Logger.info("↓↓↓↓↓区域采集↓↓↓↓↓");
|
|
|
|
|
|
Logger.info("图例名称:{}", targetFile.getName().replaceAll("\\.png",""));
|
|
|
|
|
|
Logger.info("保存路径 {}", targetFile);
|
|
|
ImgUtil.cut(capture, targetFile, new Rectangle(
|
|
|
getCaptureX(),
|
|
|
getCaptureY(),
|
|
|
getCaptureWidth(),
|
|
|
getCaptureHeight()
|
|
|
));
|
|
|
|
|
|
preferences.put(LAST_PATH, targetFile.getParent());
|
|
|
Logger.info("保存目录 {}", targetFile.getParent());
|
|
|
Logger.info("保存地址 {}", targetFile);
|
|
|
Logger.info("用法示例:");
|
|
|
Logger.info("查找图例:findLegend(\"{}\", 0.9)",targetFile.getName().replaceAll("\\.png",""));
|
|
|
Logger.info("");
|
|
|
Logger.info("↑↑↑↑↑区域采集↑↑↑↑↑");
|
|
|
}
|
|
|
|
|
|
public void close() {
|
|
|
setVisible(false);
|
|
|
dispose();
|
|
|
}
|
|
|
}
|