diff --git a/legend/城镇_L449,887.png b/legend/城镇#L449,887.png similarity index 100% rename from legend/城镇_L449,887.png rename to legend/城镇#L449,887.png diff --git a/legend/城镇_L456,887.png b/legend/城镇#L456,887.png similarity index 100% rename from legend/城镇_L456,887.png rename to legend/城镇#L456,887.png diff --git a/legend/城镇_充值_L448,36.png b/legend/城镇#充值_L448,36.png similarity index 100% rename from legend/城镇_充值_L448,36.png rename to legend/城镇#充值_L448,36.png diff --git a/legend/城镇_广告.png b/legend/城镇#广告.png similarity index 100% rename from legend/城镇_广告.png rename to legend/城镇#广告.png diff --git a/legend/城镇_探险_L35,881.png b/legend/城镇_探险#L35,881.png similarity index 100% rename from legend/城镇_探险_L35,881.png rename to legend/城镇_探险#L35,881.png diff --git a/legend/城镇_欢迎新成员_L199,773.png b/legend/城镇_欢迎新成员#L199,773.png similarity index 100% rename from legend/城镇_欢迎新成员_L199,773.png rename to legend/城镇_欢迎新成员#L199,773.png diff --git a/legend/城镇_离线收益_L204,734.png b/legend/城镇_离线收益#L204,734.png similarity index 100% rename from legend/城镇_离线收益_L204,734.png rename to legend/城镇_离线收益#L204,734.png diff --git a/legend/城镇_避难者_L3,174.png b/legend/城镇_避难者#L3,174.png similarity index 100% rename from legend/城镇_避难者_L3,174.png rename to legend/城镇_避难者#L3,174.png diff --git a/legend/探险_不可领取_L420,667.png b/legend/探险_不可领取#L420,667.png similarity index 100% rename from legend/探险_不可领取_L420,667.png rename to legend/探险_不可领取#L420,667.png diff --git a/legend/探险_按钮_L240,854.png b/legend/探险_按钮#L240,854.png similarity index 100% rename from legend/探险_按钮_L240,854.png rename to legend/探险_按钮#L240,854.png diff --git a/legend/探险_获得奖励_L196,218.png b/legend/探险_获得奖励#L196,218.png similarity index 100% rename from legend/探险_获得奖励_L196,218.png rename to legend/探险_获得奖励#L196,218.png diff --git a/legend/探险_返回_L4,4.png b/legend/探险_返回#L4,4.png similarity index 100% rename from legend/探险_返回_L4,4.png rename to legend/探险_返回#L4,4.png diff --git a/legend/探险_领取_L426,667.png b/legend/探险_领取#L426,667.png similarity index 100% rename from legend/探险_领取_L426,667.png rename to legend/探险_领取#L426,667.png diff --git a/legend/探险_领取2_L230,664.png b/legend/探险_领取2#L230,664.png similarity index 100% rename from legend/探险_领取2_L230,664.png rename to legend/探险_领取2#L230,664.png diff --git a/legend/野外_L444,888.png b/legend/野外#L444,888.png similarity index 100% rename from legend/野外_L444,888.png rename to legend/野外#L444,888.png diff --git a/legend/野外_任务_L16,759.png b/legend/野外_任务#L16,759.png similarity index 100% rename from legend/野外_任务_L16,759.png rename to legend/野外_任务#L16,759.png diff --git a/legend/野外_搜索_L226,879.png b/legend/野外_搜索#L226,879.png similarity index 100% rename from legend/野外_搜索_L226,879.png rename to legend/野外_搜索#L226,879.png diff --git a/legend/野外_木材.png b/legend/野外_木材.png deleted file mode 100644 index bf77b43..0000000 Binary files a/legend/野外_木材.png and /dev/null differ diff --git a/legend/野外_煤矿.png b/legend/野外_煤矿.png deleted file mode 100644 index 72a73a3..0000000 Binary files a/legend/野外_煤矿.png and /dev/null differ diff --git a/legend/野外_生肉.png b/legend/野外_生肉.png deleted file mode 100644 index 8f05f7e..0000000 Binary files a/legend/野外_生肉.png and /dev/null differ diff --git a/legend/野外_资源_+.png b/legend/野外_资源_+.png deleted file mode 100644 index 047491c..0000000 Binary files a/legend/野外_资源_+.png and /dev/null differ diff --git a/legend/野外_资源_-.png b/legend/野外_资源_-.png deleted file mode 100644 index f01387e..0000000 Binary files a/legend/野外_资源_-.png and /dev/null differ diff --git a/legend/野外_资源_出征.png b/legend/野外_资源_出征.png deleted file mode 100644 index cca1085..0000000 Binary files a/legend/野外_资源_出征.png and /dev/null differ diff --git a/legend/野外_资源_采集.png b/legend/野外_资源_采集.png deleted file mode 100644 index 3624116..0000000 Binary files a/legend/野外_资源_采集.png and /dev/null differ diff --git a/legend/野外_资源_采集队伍满.png b/legend/野外_资源_采集队伍满.png deleted file mode 100644 index 012d989..0000000 Binary files a/legend/野外_资源_采集队伍满.png and /dev/null differ diff --git a/legend/野外_铁矿.png b/legend/野外_铁矿.png deleted file mode 100644 index 2957c35..0000000 Binary files a/legend/野外_铁矿.png and /dev/null differ diff --git a/legend/首页_广告关闭按钮.png b/legend/首页_广告关闭按钮.png deleted file mode 100644 index 651b74a..0000000 Binary files a/legend/首页_广告关闭按钮.png and /dev/null differ diff --git a/src/main/java/com/example/jmacro/wjdr/JMacro.java b/src/main/java/com/example/jmacro/wjdr/JMacro.java index 1674a36..169adb6 100644 --- a/src/main/java/com/example/jmacro/wjdr/JMacro.java +++ b/src/main/java/com/example/jmacro/wjdr/JMacro.java @@ -1,8 +1,7 @@ package com.example.jmacro.wjdr; -import cn.hutool.core.convert.Convert; import cn.hutool.core.util.RandomUtil; -import cn.hutool.core.util.ReUtil; +import com.example.jmacro.wjdr.base.Legend; import com.example.jmacro.wjdr.base.ViewPoint; import com.example.jmacro.wjdr.base.ViewRect; import com.example.jmacro.wjdr.util.ColorUtil; @@ -35,48 +34,32 @@ public abstract class JMacro { */ protected ViewRect focusRect; - /** - * 图例目录 - */ - private File legend; - public JMacro() { try { // 机器人初始化 this.robot = new Robot(); - this.robot.setAutoDelay(100); - this.legend = new File("legend"); + this.robot.setAutoDelay(30); this.startFocus(); } catch (AWTException e) { throw new RuntimeException(e); } } - public JMacro(File legend) { - this(); - this.legend = legend; - } - public Robot getRobot() { return robot; } - public File getLegend() { - return legend; - } - - public void setLegend(File legend) { - this.legend = legend; - } - /** - * 获取视口区域 - * - * @return 视口区域 + * 开始聚焦 */ public void startFocus() { TaskUtil.asyncTask(() -> { focusRect = TaskUtil.timeTask(this::focus, 10, TimeUnit.SECONDS); + if (focusRect != null) { + Logger.info("聚焦成功"); + } else { + Logger.error("聚焦失败"); + } }); } @@ -145,7 +128,7 @@ public abstract class JMacro { int dx = (int) (startX + (point.getX() - startX) * d); int dy = (int) (startY + (point.getY() - startY) * d); robot.mouseMove(dx, dy); - robot.delay(RandomUtil.randomInt(interval - 10, interval + 10)); + delay(RandomUtil.randomInt(interval - 10, interval + 10)); } } else { robot.mouseMove(point.getX(), point.getY()); @@ -160,7 +143,7 @@ public abstract class JMacro { public void mouseLeftClick(ViewPoint rect) { mouseMove(rect); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.delay(100); + delay(100); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } @@ -265,11 +248,11 @@ public abstract class JMacro { robot.mouseMove(rect.getCenter()[0], rect.getCenter()[1]); delayUnstable(); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.delay(100); + delay(100); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - robot.delay(100); + delay(100); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.delay(100); + delay(100); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } @@ -284,86 +267,88 @@ public abstract class JMacro { * 获取聚焦区域 */ public ViewRect getFocusRect() { - return focusRect; + if (focusRect != null) { + return focusRect; + } + // 返回屏幕区域 + return getScreenRect(); } /** - * 获取屏幕范围 + * 获取聚焦区域 */ public ViewRect getScreenRect() { + if (focusRect != null) { + return focusRect; + } + // 返回屏幕区域 Toolkit tk = Toolkit.getDefaultToolkit(); return new ViewRect(0, 0, tk.getScreenSize().width, tk.getScreenSize().height); } /** - * 全屏查找图片 - * - * @param legendName 图例名称 - * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * 延迟 */ - public ViewRect findPic(String legendName, double minSimilar) { - if (!legendName.endsWith(".png")) { - legendName = legendName + ".png"; + public void delay() { + delay(100); + } + + /** + * 延迟 + */ + public void delay(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + throw new RuntimeException(e); } - return findPic(new File(legend, legendName), minSimilar); } /** - * 全屏查找图片 - * - * @param pic 图片 - * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * 抖动延迟 */ - public ViewRect findPic(File pic, double minSimilar) { - return findPic(getFocusRect(), ImageUtil.load(pic), minSimilar); + public void delayUnstable() { + delayUnstable(500); } /** - * 全屏查找图片 - * - * @param pic 图片 - * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * 抖动延迟 */ - public ViewRect findPic(BufferedImage pic, double minSimilar) { - return findPic(getFocusRect(), pic, minSimilar); + public void delayUnstable(long millis) { + if (millis < 200) { + delay(millis); + return; + } + delay(RandomUtil.randomLong(millis - 100, millis + 100)); } /** - * 应用视口查找图例 + * 全屏查找图片 * - * @param viewRect 应用视口 - * @param legendName 图例名称 + * @param pic 图片 * @param minSimilar 最低相似度 * @return 匹配图片区域 */ - public ViewRect findPic(ViewRect viewRect, String legendName, double minSimilar) { - if (!legendName.endsWith(".png")) { - legendName = legendName + ".png"; - } - return findPic(viewRect, new File(legend, legendName), minSimilar); + public ViewRect findPic(File pic, double minSimilar) { + return findPic(getFocusRect(), ImageUtil.load(pic), minSimilar); } - /** - * 应用视口查找图例 + * 全屏查找图片 * - * @param viewRect 应用视口 - * @param legend 图例文件 + * @param pic 图片 * @param minSimilar 最低相似度 * @return 匹配图片区域 */ - public ViewRect findPic(ViewRect viewRect, File legend, double minSimilar) { - return findPic(viewRect, ImageUtil.load(legend), minSimilar); + public ViewRect findPic(BufferedImage pic, double minSimilar) { + return findPic(getFocusRect(), pic, minSimilar); } /** - * 获取定位 + * 查找图片 * - * @param pic 参考图 - * @param viewRect 查找范围 + * @param viewRect 查找范围(不设时,取全屏) + * @param pic 待查找图片 * @param minSimilar 相似度 * @return 匹配图片区域 */ @@ -377,6 +362,9 @@ public abstract class JMacro { Logger.error("视口尺寸小于图片"); return null; } + if (minSimilar > 1) { + throw new RuntimeException("this minSimilar must be less than 1"); + } // 获取实时屏幕 BufferedImage screen = capture(robot, viewRect); @@ -407,281 +395,297 @@ public abstract class JMacro { if (lt && rt && lb && rb && cc) { // 统计相似点数 int samePixels = 0; - // 统计不相似点数 - int diffPixels = 0; for (int smallY = 0; smallY < pic.getHeight(); smallY++) { for (int smallX = 0; smallX < pic.getWidth(); smallX++) { if (ColorUtil.isSimilar(screenData[x + smallX][y + smallY], picData[smallX][smallY])) { samePixels++; - } else { - diffPixels++; } } } - // 计算目前相似度 + // 计算相似度 double similar = (double) samePixels / (pic.getWidth() * pic.getHeight()); if (similar >= minSimilar) { return new ViewRect(x, y, x + pic.getWidth(), y + pic.getHeight(), similar); } - // 计算目前最大相似度 - // 根据不相似像素点数推断本次可能达到的最大相似度,如果可能达到的最大相似度都小于预取相似度就不用比下去了 - double maxSimilar = 1.0d - (double) diffPixels / (pic.getWidth() * pic.getHeight()); - if (maxSimilar < minSimilar) { - return null; - } } } } return null; } - public void delay() { - delay(100); - } - - public void delay(long millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - public void delayUnstable() { - delayUnstable(500); + /** + * 等待并查找图片 + * + * @param pic 图片 + * @param minSimilar 最低相似度 + * @return 匹配图片区域 + */ + public ViewRect waitAndFindPic(File pic, double minSimilar) { + return waitAndFindPic(getFocusRect(), pic, minSimilar, 10); } - public void delayUnstable(long millis) { - if (millis < 200) { - delay(millis); - return; - } - delay(RandomUtil.randomLong(millis - 100, millis + 100)); + /** + * 等待并查找图片 + * + * @param pic 图片 + * @param minSimilar 最低相似度 + * @return 匹配图片区域 + */ + public ViewRect waitAndFindPic(BufferedImage pic, double minSimilar) { + return waitAndFindPic(getFocusRect(), pic, minSimilar, 10); } /** * 等待并查找图片 * - * @param file 图例 + * @param pic 图片 * @param minSimilar 最低相似度 + * @param seconds 最长等待秒数 * @return 匹配图片区域 */ - public ViewRect waitAndFindPic(File file, double minSimilar) { - return waitAndFindPic(getFocusRect(), file, minSimilar, 10, TimeUnit.SECONDS); + public ViewRect waitAndFindPic(File pic, double minSimilar, long seconds) { + return waitAndFindPic(getFocusRect(), pic, minSimilar, seconds); } /** * 等待并查找图片 * - * @param rect 查找区域 - * @param file 图例 + * @param pic 图片 * @param minSimilar 最低相似度 + * @param seconds 最长等待秒数 * @return 匹配图片区域 */ - public ViewRect waitAndFindPic(ViewRect rect, File file, double minSimilar) { - return waitAndFindPic(rect, file, minSimilar, 10, TimeUnit.SECONDS); + public ViewRect waitAndFindPic(BufferedImage pic, double minSimilar, long seconds) { + return waitAndFindPic(getFocusRect(), pic, minSimilar, seconds); } /** * 等待并查找图片 * * @param rect 查找区域 - * @param legendName 图例名称 + * @param pic 图片 * @param minSimilar 最低相似度 * @return 匹配图片区域 */ - public ViewRect waitAndFindPic(ViewRect rect, String legendName, double minSimilar) { - if (!legendName.endsWith(".png")) { - legendName = legendName + ".png"; - } - return waitAndFindPic(rect, new File(legend, legendName), minSimilar, 10, TimeUnit.SECONDS); + public ViewRect waitAndFindPic(ViewRect rect, File pic, double minSimilar) { + return waitAndFindPic(rect, pic, minSimilar, 10); } /** * 等待并查找图片 * - * @param file 图例 + * @param rect 查找区域 + * @param pic 图片 * @param minSimilar 最低相似度 - * @param time 最长等待时间 - * @param unit 最长等待时间单位 + * @param seconds 最长等待秒数 * @return 匹配图片区域 */ - public ViewRect waitAndFindPic(File file, double minSimilar, long time, TimeUnit unit) { - return waitAndFindPic(getFocusRect(), file, minSimilar, time, unit); + public ViewRect waitAndFindPic(ViewRect rect, File pic, double minSimilar, long seconds) { + return waitAndFindPic(rect, ImageUtil.load(pic), minSimilar, seconds); } /** * 等待并查找图片 * * @param rect 查找区域 - * @param legendName 图例名称 + * @param pic 图片 * @param minSimilar 最低相似度 - * @param time 最长等待时间 - * @param unit 最长等待时间单位 * @return 匹配图片区域 */ - public ViewRect waitAndFindPic(ViewRect rect, String legendName, double minSimilar, long time, TimeUnit unit) { - if (!legendName.endsWith(".png")) { - legendName = legendName + ".png"; - } - return waitAndFindPic(rect, new File(legend, legendName), minSimilar, time, unit); + public ViewRect waitAndFindPic(ViewRect rect, BufferedImage pic, double minSimilar) { + return waitAndFindPic(rect, pic, minSimilar, 10); } /** * 等待并查找图片 * * @param rect 查找区域 - * @param file 图例 + * @param pic 图片 * @param minSimilar 最低相似度 - * @param time 最长等待时间 - * @param unit 最长等待时间单位 + * @param seconds 最长等待秒数 * @return 匹配图片区域 */ - public ViewRect waitAndFindPic(ViewRect rect, File file, double minSimilar, long time, TimeUnit unit) { + public ViewRect waitAndFindPic(ViewRect rect, BufferedImage pic, double minSimilar, long seconds) { + if (rect.getWidth() < pic.getWidth()) { + Logger.error("查找图片区域宽度{}小于图片宽度{}", rect.getWidth(), pic.getWidth()); + return null; + } + if (rect.getHeight() < pic.getHeight()) { + Logger.error("查找图片区域宽度{}小于图片宽度{}", rect.getHeight(), pic.getHeight()); + return null; + } return TaskUtil.timeTask(() -> { - BufferedImage image = ImageUtil.load(file); - if (rect.getWidth() < image.getWidth()) { - Logger.error("查找图片区域宽度{}小于图片宽度{}", rect.getWidth(), image.getWidth()); - return null; - } - if (rect.getHeight() < image.getHeight()) { - Logger.error("查找图片区域宽度{}小于图片宽度{}", rect.getHeight(), image.getHeight()); - return null; - } - - while (true) { + while (JMainService.getInstance().run) { delayUnstable(); - ViewRect pic = findPic(rect, image, minSimilar); - if (pic != null) { - return pic; + ViewRect result = findPic(rect, pic, minSimilar); + if (result != null) { + return result; } } - }, time, unit); + return null; + }, seconds, TimeUnit.SECONDS); } /** - * 等待并匹配图例 + * 匹配图片 * - * @param rect 参照区域 - * @param legendName 图例名称 + * @param pic 图片 + * @param location 定位 * @param minSimilar 最低相似度 - * @return 匹配图片区域 + * @return 匹配图片 */ - public ViewRect waitAndMatchPic(ViewRect rect, String legendName, double minSimilar) { - if (!legendName.endsWith(".png")) { - legendName = legendName + ".png"; + public ViewRect matchPic(File pic, ViewPoint location, double minSimilar) { + if (!pic.exists()) { + Logger.error("file [{}] not exist", pic.getAbsolutePath()); + return null; } - return waitAndMatchPic(rect, new File(legend, legendName), minSimilar, 3, TimeUnit.SECONDS); + return matchPic(ImageUtil.load(pic), location, minSimilar); + } + + public ViewRect matchPic(BufferedImage pic, ViewPoint location, double minSimilar) { + ViewRect focusRect = getFocusRect(); + int offsetX = location.getX(); + int offsetY = location.getY(); + ViewRect viewRect = new ViewRect(); + viewRect.setLeft(focusRect.getLeft() + offsetX); + viewRect.setTop(focusRect.getTop() + offsetY); + viewRect.setRight(viewRect.getLeft() + pic.getWidth()); + viewRect.setBottom(viewRect.getTop() + pic.getHeight()); + ImageUtil.show(viewRect); + return findPic(viewRect, pic, minSimilar); } /** - * 等待并匹配图例 + * 等待并匹配图片 * - * @param rect 参照区域 - * @param file 图例 + * @param pic 图片 * @param minSimilar 最低相似度 * @return 匹配图片区域 */ - public ViewRect waitAndMatchPic(ViewRect rect, File file, double minSimilar) { - return waitAndMatchPic(rect, file, minSimilar, 3, TimeUnit.SECONDS); + public ViewRect waitAndMatchPic(File pic, ViewPoint location, double minSimilar) { + return waitAndMatchPic(ImageUtil.load(pic), location, minSimilar); } /** - * 等待并匹配图例 + * 等待并匹配图片 + * + * @param pic 图片 + * @param minSimilar 最低相似度 + * @return 匹配图片区域 + */ + public ViewRect waitAndMatchPic(BufferedImage pic, ViewPoint location, double minSimilar) { + return waitAndMatchPic(pic, location, minSimilar, 10); + } + + /** + * 等待并匹配图片 * - * @param rect 参照区域 - * @param file 图例 + * @param pic 图片 * @param minSimilar 最低相似度 - * @param time 最长等待时间 - * @param unit 最长等待时间单位 + * @param seconds 最长等待秒数 * @return 匹配图片区域 */ - public ViewRect waitAndMatchPic(ViewRect rect, File file, double minSimilar, long time, TimeUnit unit) { + public ViewRect waitAndMatchPic(File pic, ViewPoint location, double minSimilar, long seconds) { + return waitAndMatchPic(ImageUtil.load(pic), location, minSimilar, seconds); + } + + /** + * 等待并匹配图片 + * + * @param pic 图片 + * @param minSimilar 最低相似度 + * @param seconds 最长等待秒数 + * @return 匹配图片区域 + */ + public ViewRect waitAndMatchPic(BufferedImage pic, ViewPoint location, double minSimilar, long seconds) { return TaskUtil.timeTask(() -> { while (JMainService.getInstance().run) { - ViewRect matchPic = matchPic(rect, file, minSimilar); + ViewRect matchPic = matchPic(pic, location, minSimilar); if (matchPic != null) { return matchPic; } } return null; - }, time, unit); + }, seconds, TimeUnit.SECONDS); + } + + /** + * 匹配图例 + * + * @param legend 图例 + * @param minSimilar 最低相似度 + * @return 匹配图片 + */ + public ViewRect matchLegend(String legend, double minSimilar) { + return matchLegend(Legend.inflate(legend), minSimilar); } /** * 匹配图片 * - * @param rect 程序窗口(参照系) - * @param file 图例 + * @param legend 图例 * @param minSimilar 最低相似度 * @return 匹配图片 */ - public ViewRect matchPic(ViewRect rect, File file, double minSimilar) { + public ViewRect matchLegend(Legend legend, double minSimilar) { if (minSimilar > 1) { throw new RuntimeException("this minSimilar must be less than 1"); } - if (!file.exists()) { - Logger.error("file [{}] not exist", file.getAbsolutePath()); - return null; - } - String name = file.getName(); - int offsetX = 0; - int offsetY = 0; - if (name.matches("[\\S\\s]+_L[0-9]+,[0-9]+\\.png")) { - offsetX = Convert.toInt(ReUtil.get("[\\S\\s]+_L([0-9]+),[0-9]+\\.png", name, 1), 0); - offsetY = Convert.toInt(ReUtil.get("[\\S\\s]+_L[0-9]+,([0-9]+)\\.png", name, 1), 0); - } + int offsetX = legend.getLocation().getX(); + int offsetY = legend.getLocation().getY(); ViewRect viewRect = new ViewRect(); - viewRect.setLeft(rect.getLeft() + offsetX); - viewRect.setTop(rect.getTop() + offsetY); - BufferedImage image = ImageUtil.load(file); + viewRect.setLeft(getFocusRect().getLeft() + offsetX); + viewRect.setTop(getFocusRect().getTop() + offsetY); + BufferedImage image = ImageUtil.load(legend.getFile()); viewRect.setRight(viewRect.getLeft() + image.getWidth()); viewRect.setBottom(viewRect.getTop() + image.getHeight()); - - ViewRect pic = findPic(viewRect, image, minSimilar); ImageUtil.show(viewRect); - return pic; + return findPic(viewRect, image, minSimilar); } /** - * 匹配图片 + * 等待并匹配图例 * - * @param rect 程序窗口(参照系) - * @param legendName 图例名称 + * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片 + * @return 匹配图片区域 */ - public ViewRect matchPic(ViewRect rect, String legendName, double minSimilar) { - if (!legendName.endsWith(".png")) { - legendName = legendName + ".png"; - } - return matchPic(rect, new File(legend, legendName), minSimilar); + public ViewRect waitAndMatchLegend(String legend, double minSimilar) { + return waitAndMatchLegend(Legend.inflate(legend), minSimilar); } /** - * 是否匹配图片 + * 等待并匹配图例 * - * @param rect 程序窗口(参照系) - * @param file 图例 + * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片 + * @return 匹配图片区域 */ - public boolean isMatchPic(ViewRect rect, File file, double minSimilar) { - return matchPic(rect, file, minSimilar) != null; + public ViewRect waitAndMatchLegend(Legend legend, double minSimilar) { + return waitAndMatchLegend(legend, minSimilar, 5); } /** - * 是否匹配图片 + * 等待并匹配图例 * - * @param rect 程序窗口(参照系) - * @param legendName 图例名称 + * @param legend 图例 * @param minSimilar 最低相似度 - * @return 匹配图片 + * @param seconds 最长等待秒数 + * @return 匹配图片区域 */ - public boolean isMatchPic(ViewRect rect, String legendName, double minSimilar) { - if (!legendName.endsWith(".png")) { - legendName = legendName + ".png"; - } - return matchPic(rect, new File(legend, legendName), minSimilar) != null; + public ViewRect waitAndMatchLegend(String legend, double minSimilar, long seconds) { + return waitAndMatchLegend(Legend.inflate(legend), minSimilar, seconds); + } + + /** + * 等待并匹配图例 + * + * @param legend 图例 + * @param minSimilar 最低相似度 + * @param seconds 最长等待秒数 + * @return 匹配图片区域 + */ + public ViewRect waitAndMatchLegend(Legend legend, double minSimilar, long seconds) { + return waitAndMatchPic(legend.getFile(), legend.getLocation(), minSimilar, seconds); } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/jmacro/wjdr/JMainApplication.java b/src/main/java/com/example/jmacro/wjdr/JMainApplication.java index 0eaec08..a7ce499 100644 --- a/src/main/java/com/example/jmacro/wjdr/JMainApplication.java +++ b/src/main/java/com/example/jmacro/wjdr/JMainApplication.java @@ -1,15 +1,19 @@ package com.example.jmacro.wjdr; -import com.example.jmacro.wjdr.demo.MacroForWJDR; +import com.example.jmacro.wjdr.base.ViewRect; import com.example.jmacro.wjdr.ui.FXMLUtil; import com.example.jmacro.wjdr.util.Logger; import com.example.jmacro.wjdr.util.ResourceUtil; +import com.melloware.jintellitype.JIntellitype; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.stage.Stage; +import java.awt.event.KeyEvent; +import java.io.File; + /** * UI入口 * @@ -19,6 +23,9 @@ import javafx.stage.Stage; */ public class JMainApplication extends Application { + public static final int F1_SHORTCUT = 1; // 开始快捷键 + public static final int F2_SHORTCUT = 2; // 结束快捷键 + public static Stage primaryStage; public static JMainController mainController; @@ -44,8 +51,35 @@ public class JMainApplication extends Application { // 展示UI stage.show(); JMainApplication.primaryStage = stage; + + JIntellitype.getInstance().registerHotKey(F1_SHORTCUT, 0, KeyEvent.VK_F1); + JIntellitype.getInstance().registerHotKey(F2_SHORTCUT, 0, KeyEvent.VK_F2); + JIntellitype.getInstance().addHotKeyListener(identifier -> { + switch (identifier) { + case F1_SHORTCUT: + mainController.onStart(); + break; + case F2_SHORTCUT: + mainController.onStop(); + break; + } + }); + // 服务初始化 - JMainService.init(new MacroForWJDR()); + JMainService.init(new JMacro() { + @Override + public ViewRect focus() { + return new ViewRect(0, 0, 200, 200); + } + + @Override + public void run() { + ViewRect pic = matchLegend("回收站", 0.9); + if (pic != null) { + mouseLeftDoubleClick(pic); + } + } + }, new File("legend")); } public static void main(String[] args) { diff --git a/src/main/java/com/example/jmacro/wjdr/JMainController.java b/src/main/java/com/example/jmacro/wjdr/JMainController.java index 9f171da..d3ce3b6 100644 --- a/src/main/java/com/example/jmacro/wjdr/JMainController.java +++ b/src/main/java/com/example/jmacro/wjdr/JMainController.java @@ -1,5 +1,6 @@ package com.example.jmacro.wjdr; +import com.example.jmacro.wjdr.base.Legend; import com.example.jmacro.wjdr.base.ViewRect; import com.example.jmacro.wjdr.tool.Capture; import com.example.jmacro.wjdr.tool.Location; @@ -9,7 +10,6 @@ import javafx.scene.control.Button; import javafx.scene.image.ImageView; import java.awt.*; -import java.io.File; /** * UI控制器 @@ -33,15 +33,14 @@ public class JMainController { * 截图 */ @FXML - private void onCapture() { + public void onCapture() { ViewRect screen = JMainService.getInstance().getMacro().getFocusRect(); - File legend = JMainService.getInstance().getMacro().getLegend(); if (screen == null) { DialogUtil.alert("未定位到视口,请稍后再试!"); return; } try { - new Capture(screen.getLeft(), screen.getTop(), legend); + new Capture(screen.getLeft(), screen.getTop(), Legend.getDefaultBase()); } catch (AWTException awtException) { awtException.printStackTrace(); } @@ -51,9 +50,8 @@ public class JMainController { * 截图 */ @FXML - private void onLocation() { + public void onLocation() { ViewRect screen = JMainService.getInstance().getMacro().getFocusRect(); - File legend = JMainService.getInstance().getMacro().getLegend(); if (screen == null) { DialogUtil.alert("未定位到视口,请稍后再试!"); return; @@ -69,7 +67,7 @@ public class JMainController { * 截图 */ @FXML - private void onStart() { + public void onStart() { boolean start = JMainService.start(); this.start.setDisable(start); this.stop.setDisable(!start); @@ -79,7 +77,7 @@ public class JMainController { * 截图 */ @FXML - private void onStop() { + public void onStop() { boolean stop = JMainService.stop(); this.start.setDisable(!stop); this.stop.setDisable(stop); diff --git a/src/main/java/com/example/jmacro/wjdr/JMainService.java b/src/main/java/com/example/jmacro/wjdr/JMainService.java index d25c02a..ad9ea18 100644 --- a/src/main/java/com/example/jmacro/wjdr/JMainService.java +++ b/src/main/java/com/example/jmacro/wjdr/JMainService.java @@ -1,6 +1,7 @@ package com.example.jmacro.wjdr; import cn.hutool.core.thread.ThreadUtil; +import com.example.jmacro.wjdr.base.Legend; import com.example.jmacro.wjdr.demo.MacroForWJDR; import com.example.jmacro.wjdr.util.DialogUtil; import com.example.jmacro.wjdr.util.Logger; @@ -54,8 +55,9 @@ public class JMainService { return macro; } - public static void init(JMacro macro) { + public static void init(JMacro macro, File legendDir) { getInstance().macro = macro; + Legend.setDefaultBase(legendDir); } public void createDaemon() { @@ -99,17 +101,6 @@ public class JMainService { return true; } - /** - * 设置图例路径 - * - * @param legend 图例路径 - */ - public static void setLegend(File legend) { - if (getInstance().macro != null) { - getInstance().macro.setLegend(legend); - } - } - /** * 守护线程 */ @@ -123,9 +114,10 @@ public class JMainService { } while (run) { try { - macro.run(); ThreadUtil.sleep(1000); + macro.run(); } catch (Exception e) { + e.printStackTrace(); Logger.error("异常中断"); } } @@ -137,7 +129,7 @@ public class JMainService { * 服务启动入口 */ public static void main(String[] args) { - JMainService.init(new MacroForWJDR()); + JMainService.init(new MacroForWJDR(), new File("legend")); JMainService.start(); } } diff --git a/src/main/java/com/example/jmacro/wjdr/base/Legend.java b/src/main/java/com/example/jmacro/wjdr/base/Legend.java new file mode 100644 index 0000000..4713378 --- /dev/null +++ b/src/main/java/com/example/jmacro/wjdr/base/Legend.java @@ -0,0 +1,119 @@ +package com.example.jmacro.wjdr.base; + +import cn.hutool.cache.Cache; +import cn.hutool.cache.CacheUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.ReUtil; + +import java.io.File; +import java.util.List; + +/** + * 图例 + *

+ * 图例分带坐标和不带坐标图例 + *

+ * 其中带坐标图例,通过将坐标融合进文件名称实现,定义如下 + * 以something#L0,0.png为例 + * 图例名称:something + * 图例坐标:#L0,0(在实例化时转为location) + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class Legend { + + /** + * 默认图例目录 + */ + private static File defaultBase = new File("legend"); + + /** + * 图例缓存 + */ + public static Cache fileCache = CacheUtil.newLFUCache(999); + + /** + * 图例目录 + */ + private File base; + + /** + * 图例文件 + */ + private File file; + + /** + * 图例名称 + */ + private String name; + + /** + * 图例坐标 + */ + private ViewPoint location; + + public static void setDefaultBase(File base) { + defaultBase = base; + } + + public static File getDefaultBase() { + return defaultBase; + } + + private Legend() { + + } + + /** + * 获取图例 + * + * @param name 图例名称 + * @return 图例 + */ + public static Legend inflate(String name) { + Legend legend = fileCache.get(name); + if (legend != null) { + return legend; + } + + List files = FileUtil.loopFiles(defaultBase, pathname -> pathname.getName().startsWith(name)); + if (files.size() == 0) { + throw new RuntimeException("Not found the legend of " + name); + } + File file = files.get(0); + Legend newLegend = new Legend(); + newLegend.base = defaultBase; + newLegend.file = file; + newLegend.name = name; + + if (!name.matches("[\\S\\s]+#L[0-9]+,[0-9]+\\.png")) { + newLegend.location = null; + } else { + int x = Convert.toInt(ReUtil.get("[\\S\\s]+#L([0-9]+),[0-9]+\\.png", file.getName(), 1), 0); + int y = Convert.toInt(ReUtil.get("[\\S\\s]+#L[0-9]+,([0-9]+)\\.png", file.getName(), 1), 0); + newLegend.location = new ViewPoint(x, y); + } + + fileCache.put(name, newLegend); + return newLegend; + } + + public File getBase() { + return base; + } + + public File getFile() { + return file; + } + + public String getName() { + return name; + } + + public ViewPoint getLocation() { + return location; + } +} diff --git a/src/main/java/com/example/jmacro/wjdr/demo/MacroForWJDR.java b/src/main/java/com/example/jmacro/wjdr/demo/MacroForWJDR.java index c7b8623..5b1faee 100644 --- a/src/main/java/com/example/jmacro/wjdr/demo/MacroForWJDR.java +++ b/src/main/java/com/example/jmacro/wjdr/demo/MacroForWJDR.java @@ -4,13 +4,15 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.date.DateUtil; import com.example.jmacro.wjdr.JMacro; import com.example.jmacro.wjdr.JMainService; +import com.example.jmacro.wjdr.base.Legend; import com.example.jmacro.wjdr.base.ViewRect; -import com.example.jmacro.wjdr.demo.task.*; +import com.example.jmacro.wjdr.demo.task.Task_探险领取; +import com.example.jmacro.wjdr.demo.task.Task_收留避难者; +import com.example.jmacro.wjdr.demo.task.Task_离线收益; +import com.example.jmacro.wjdr.demo.task.Task_采矿被攻击; import com.example.jmacro.wjdr.util.Logger; import com.example.jmacro.wjdr.util.TaskUtil; -import java.util.concurrent.TimeUnit; - /** * 无尽冬日脚本 * @@ -39,7 +41,7 @@ public class MacroForWJDR extends JMacro { public synchronized ViewRect focus() { // 定位窗口 Logger.info("定位窗口"); - ViewRect mumu = findPic("慕慕_工具栏", 0.95d); + ViewRect mumu = findPic(Legend.inflate("慕慕_工具栏").getFile(), 0.95d); if (mumu == null) { Logger.error("定位窗口失败"); return null; @@ -63,7 +65,7 @@ public class MacroForWJDR extends JMacro { Logger.info("任务线程ID={}", Thread.currentThread().getId()); // 获取启动图标 Logger.info("定位启动图标"); - ViewRect launch = waitAndFindPic(focusRect, "启动图标", 0.9, 10, TimeUnit.SECONDS); + ViewRect launch = waitAndFindPic(Legend.inflate("启动图标").getFile(), 0.9); if (launch != null) { Logger.info("启动图标坐标:", launch.toString()); Logger.info("启动程序"); @@ -78,14 +80,14 @@ public class MacroForWJDR extends JMacro { // 定位城镇 Boolean inMain = TaskUtil.retryTask(() -> { { // 定位弹框,关闭弹框 - ViewRect rect = matchPic(focusRect, "城镇_充值_L448,36", 0.8d); + ViewRect rect = waitAndMatchLegend("城镇_充值", 0.8d); if (rect != null) { mouseLeftClick(rect); Logger.info("检测到充值广告弹框,关闭弹框"); } } {// 定位离线收益 - ViewRect rect = matchPic(focusRect, "城镇_离线收益_L204,734", 0.9); + ViewRect rect = waitAndMatchLegend("城镇_离线收益", 0.9); if (rect != null) { mouseLeftClick(rect); Logger.info("检测到离线收益弹框,关闭弹框"); @@ -93,7 +95,7 @@ public class MacroForWJDR extends JMacro { } // 定位城镇 { - ViewRect rect = matchPic(focusRect, "城镇_L456,887", 0.9); + ViewRect rect = waitAndMatchLegend("城镇", 0.9); if (rect != null) { Logger.info("当前区域【野外】"); Logger.info("返回区域【城镇】"); @@ -102,7 +104,7 @@ public class MacroForWJDR extends JMacro { } } {// 定位野外 - ViewRect rect = matchPic(focusRect, "野外_L444,888", 0.9); + ViewRect rect = waitAndMatchLegend("野外", 0.9); if (rect != null) { Logger.info("当前区域【城镇】"); return true; diff --git a/src/main/java/com/example/jmacro/wjdr/demo/task/Task_探险领取.java b/src/main/java/com/example/jmacro/wjdr/demo/task/Task_探险领取.java index 8845f00..72a510c 100644 --- a/src/main/java/com/example/jmacro/wjdr/demo/task/Task_探险领取.java +++ b/src/main/java/com/example/jmacro/wjdr/demo/task/Task_探险领取.java @@ -13,7 +13,7 @@ public class Task_探险领取 extends BaseTask { @Override public void task(JMacro macro, ViewRect viewRect) { Logger.info("定位【探险】按钮"); - ViewRect TAB_探险 = macro.waitAndMatchPic(this.viewRect, "城镇_探险_L35,881", 0.9); + ViewRect TAB_探险 = macro.waitAndMatchLegend("城镇_探险", 0.9); if (TAB_探险 == null) { return; } @@ -21,7 +21,7 @@ public class Task_探险领取 extends BaseTask { Logger.info("点击【探险】按钮"); macro.mouseLeftClick(TAB_探险); - ViewRect 探险_按钮 = macro.waitAndMatchPic(this.viewRect, "探险_按钮_L240,854", 0.9); + ViewRect 探险_按钮 = macro.waitAndMatchLegend("探险_按钮", 0.9); if (探险_按钮 == null) { Logger.info("进入探险界面失败"); return; @@ -29,26 +29,26 @@ public class Task_探险领取 extends BaseTask { Logger.info("进入探险界面成功"); Logger.info("定位领取按钮"); - ViewRect 探险_不可领取 = macro.waitAndMatchPic(this.viewRect, "探险_不可领取_L420,667", 0.8); + ViewRect 探险_不可领取 = macro.waitAndMatchLegend("探险_不可领取", 0.8); if (探险_不可领取 != null) { Logger.info("探险不可领取"); } else { Logger.info("定位领取按钮"); - ViewRect 探险_领取 = macro.waitAndMatchPic(this.viewRect, "探险_领取_L426,667", 0.8); + ViewRect 探险_领取 = macro.waitAndMatchLegend("探险_领取", 0.8); if (探险_领取 == null) { Logger.error("未检测到【探险_领取】,领取终止"); return; } Logger.info("定位领取按钮成功,准备领取:{}", 探险_领取.toString()); macro.mouseLeftClick(探险_领取); - ViewRect 探险_领取2 = macro.waitAndMatchPic(this.viewRect, "探险_领取2_L230,664", 0.8); + ViewRect 探险_领取2 = macro.waitAndMatchLegend("探险_领取2", 0.8); if (探险_领取2 == null) { Logger.error("任务终止"); return; } macro.mouseLeftClick(探险_领取2); - ViewRect 探险_获得奖励 = macro.waitAndMatchPic(this.viewRect, "探险_获得奖励_L196,218", 0.8); + ViewRect 探险_获得奖励 = macro.waitAndMatchLegend("探险_获得奖励", 0.8); if (探险_获得奖励 == null) { Logger.error("任务终止"); return; @@ -56,7 +56,7 @@ public class Task_探险领取 extends BaseTask { macro.mouseLeftClick(探险_获得奖励); } - ViewRect 探险_返回 = macro.waitAndMatchPic(this.viewRect, "探险_返回_L4,4", 0.8); + ViewRect 探险_返回 = macro.waitAndMatchLegend("探险_返回", 0.8); if (探险_返回 == null) { Logger.error("任务终止"); return; diff --git a/src/main/java/com/example/jmacro/wjdr/demo/task/Task_收留避难者.java b/src/main/java/com/example/jmacro/wjdr/demo/task/Task_收留避难者.java index e305ff3..79ad7ea 100644 --- a/src/main/java/com/example/jmacro/wjdr/demo/task/Task_收留避难者.java +++ b/src/main/java/com/example/jmacro/wjdr/demo/task/Task_收留避难者.java @@ -12,7 +12,7 @@ public class Task_收留避难者 extends BaseTask { @Override public void task(JMacro macro, ViewRect viewRect) { - ViewRect rect = macro.waitAndMatchPic(viewRect, "城镇_避难者_L3,174", 0.9); + ViewRect rect = macro.waitAndMatchLegend("城镇_避难者", 0.9); if (rect == null) { Logger.info("未发现避难者"); return; @@ -23,7 +23,7 @@ public class Task_收留避难者 extends BaseTask { macro.mouseLeftClick(rect); macro.delayUnstable(); - ViewRect rect1 = macro.waitAndMatchPic(viewRect, "城镇_欢迎新成员_L199,773", 0.9); + ViewRect rect1 = macro.waitAndMatchLegend("城镇_欢迎新成员", 0.9); if (rect1 == null) { Logger.info("收留避难者异常"); return; diff --git a/src/main/java/com/example/jmacro/wjdr/demo/task/Task_离线收益.java b/src/main/java/com/example/jmacro/wjdr/demo/task/Task_离线收益.java index 8c84b14..72a9237 100644 --- a/src/main/java/com/example/jmacro/wjdr/demo/task/Task_离线收益.java +++ b/src/main/java/com/example/jmacro/wjdr/demo/task/Task_离线收益.java @@ -14,7 +14,7 @@ public class Task_离线收益 extends BaseTask { public void task(JMacro macro, ViewRect viewRect) { macro.delay(); // 定位离线收益弹框,关闭弹框 - ViewRect rect = macro.matchPic(viewRect, "城镇_离线收益_L204,734", 0.9); + ViewRect rect = macro.waitAndMatchLegend("城镇_离线收益", 0.9); if (rect != null) { macro.mouseLeftClick(rect); Logger.info("检测到离线收益弹框,关闭弹框"); diff --git a/src/main/java/com/example/jmacro/wjdr/demo/task/Task_自动采矿.java b/src/main/java/com/example/jmacro/wjdr/demo/task/Task_自动采矿.java index b8476c2..6212005 100644 --- a/src/main/java/com/example/jmacro/wjdr/demo/task/Task_自动采矿.java +++ b/src/main/java/com/example/jmacro/wjdr/demo/task/Task_自动采矿.java @@ -17,12 +17,12 @@ public class Task_自动采矿 extends BaseTask { @Override public void task(JMacro macro, ViewRect viewRect) { Logger.info("判断是否在野外"); - ViewRect 城镇 = macro.waitAndMatchPic(this.viewRect, "城镇_L449,887", 0.9); + ViewRect 城镇 = macro.waitAndMatchLegend( "城镇", 0.9); if (城镇 != null) { Logger.info("当前界面【野外】"); } else { Logger.info("定位【野外】"); - ViewRect 野外 = macro.waitAndMatchPic(this.viewRect, "野外_L444,888", 0.99); + ViewRect 野外 = macro.waitAndMatchLegend( "野外", 0.99); if (野外 == null) { Logger.error("定位【野外】失败,采矿终止"); return; @@ -36,7 +36,7 @@ public class Task_自动采矿 extends BaseTask { Logger.info("定位资源搜索按钮"); // 因为搜索按钮透明,不好比对,通过定位其下面的任务图标定位 - ViewRect 野外_任务 = macro.waitAndMatchPic(this.viewRect, "野外_任务_L16,759", 0.9); + ViewRect 野外_任务 = macro.waitAndMatchLegend( "野外_任务", 0.9); if (野外_任务 == null) { Logger.error("未检测到【资源搜索按钮】,采矿终止"); return; @@ -49,14 +49,13 @@ public class Task_自动采矿 extends BaseTask { // 因为搜索按钮透明,不好比对,通过定位其下面的任务图标定位 - ViewRect 野外_搜索 = macro.waitAndMatchPic(this.viewRect, "野外_搜索_L226,879", 0.9); + ViewRect 野外_搜索 = macro.waitAndMatchLegend( "野外_搜索#L226,879.png", 0.9); if (野外_搜索 == null) { Logger.error("未检测到【野外_搜索】,采矿终止"); return; } // todo - String[] types = new String[]{ "生肉", "木材", "煤矿", "铁矿" }; @@ -69,13 +68,13 @@ public class Task_自动采矿 extends BaseTask { } // 检测是否是搜索界面 - ViewRect 野外_任务2 = macro.waitAndMatchPic(this.viewRect, "野外_任务_L16,759", 9); + ViewRect 野外_任务2 = macro.waitAndMatchLegend( "野外_任务", 9); if (野外_任务2 != null) { Logger.info("退出资源搜索界面"); macro.mouseLeftClick(this.viewRect); } - ViewRect 城1 = macro.waitAndMatchPic(this.viewRect, "城镇_L456,887", 0.9); + ViewRect 城1 = macro.waitAndMatchLegend( "城镇", 0.9); if (城1 == null) { Logger.error("未检测到【城镇】,采矿终止"); return; diff --git a/src/main/java/com/example/jmacro/wjdr/tool/Capture.java b/src/main/java/com/example/jmacro/wjdr/tool/Capture.java index 7af7cbb..da499e1 100644 --- a/src/main/java/com/example/jmacro/wjdr/tool/Capture.java +++ b/src/main/java/com/example/jmacro/wjdr/tool/Capture.java @@ -1,15 +1,26 @@ package com.example.jmacro.wjdr.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 com.example.jmacro.wjdr.base.Legend; +import com.example.jmacro.wjdr.util.DialogUtil; import com.example.jmacro.wjdr.util.Logger; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.*; -import java.awt.event.*; +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.prefs.Preferences; /** @@ -40,23 +51,26 @@ public class Capture extends JFrame { /** * 背景蒙层 */ - private Color mask = new Color(0, 0, 0, 0.2f); + private final Color mask = new Color(0, 0, 0, 0.2f); /** * 聚焦框线条 */ - private Stroke focusWindow = new BasicStroke(1.0f); + private final Stroke focusWindow = new BasicStroke(1.0f); /** * 屏幕截图区域起始坐标 */ - private Point start = new Point(0, 0); + private final Point start = new Point(0, 0); /** * 屏幕截图区域结束坐标 */ - private Point end = new Point(0, 0); + private final Point end = new Point(0, 0); + /** + * 个人首选项配置工具 + */ private Preferences preferences; /** @@ -192,8 +206,8 @@ public class Capture extends JFrame { // 上一次保存目录 String lastPath = preferences.get(LAST_PATH, ""); // 默认文件名 - String location = "_L" + (getCaptureX() - originX) + "," + (getCaptureY() - originY); - String filename = System.currentTimeMillis() + location + ".png"; + String location = "L" + (getCaptureX() - originX) + "," + (getCaptureY() - originY); + String filename = StrUtil.format("{}#{}.png", System.currentTimeMillis(), location); JFileChooser jFileChooser = new JFileChooser(); jFileChooser.setFileFilter(new FileNameExtensionFilter("png", "png")); @@ -204,8 +218,23 @@ public class Capture extends JFrame { if (returnVal == JFileChooser.APPROVE_OPTION) { // 默认文件 File file = jFileChooser.getSelectedFile(); - // 修正坐标 - filename = file.getName().replaceAll("(_L[0-9]+,[0-9]+)?.png", "") + location + ".png"; + String name = file.getName(); + String legendName = name.split("#")[0]; + String prefix = legendName + "#"; + + List files = FileUtil.loopFiles(Legend.getDefaultBase(), pathname -> pathname.getName().startsWith(prefix)); + if (files.size() > 0) { + DialogUtil.confirm("提示", "存在相同图例,是否旧的删除?", result -> { + if (result) { + for (File file1 : files) { + file1.deleteOnExit(); + } + } + }); + } + + // 图例文件名 + filename = StrUtil.format("{}#{}.png", legendName, location); file = new File(file.getParent(), filename); Logger.info("保存路径" + file); diff --git a/src/main/resources/main.fxml b/src/main/resources/main.fxml index 8077d1b..cb9d9c6 100644 --- a/src/main/resources/main.fxml +++ b/src/main/resources/main.fxml @@ -17,8 +17,8 @@ -