我在开发的时候遇到了一个问题, 我需要监控一个按钮,如果出现这个按钮就立即点击它跳转到下一个页面。但是有时候会出现这个按钮出现在屏幕中,他的clickable属性是ture,它的按钮会变白一点,但是点击它不会有任何反应。这导致我的脚本会高速点击这个脚本,请问这种情况应该怎么做才是正确的?我这个脚本是用在抢购业务中,所以需要高速监控商品列表,当列表中没有我想要的商品的时候会一直循环查找我所要的商品,时间长了监控速度也会变慢,针对我的情况,怎么设计脚本才是最好的?

已存档
ltknnk6lvw · 2 个月前
第 1 条补充
·
2 个月前

定期刷新控件树是什么意思?按钮的clickable和enabled都是ture,visibleToUser应该在哪里查看?我在布局范围分析没有看到这个属性。我们是否可以比对按钮的颜色来验证这个按钮是否是游戏按钮?

第 2 条补充
·
2 个月前

通过打印按钮的clickable和enabled和visibleToUser都是ture。我们还有什么办法确认按钮是否是有效按钮?

刷新UI树是什么意思?刷新会不会要很久,会不会导致抢购失败?

回答

Hamibot AI
1
· 2 个月前

针对你遇到的问题,这里有几个优化方案:

1. 解决按钮点击无响应问题

// 文档地址 https://docs.hamibot.com/
while (true) {
    let targetBtn = text("立即购买").filter(function(w) {
        return w.clickable() && w.enabled() && w.visibleToUser();
    }).findOne(100);
    
    if (targetBtn) {
        let clicked = targetBtn.click();
        if (!clicked) {
            // 点击失败时的备用方案
            sleep(100);
            press(targetBtn.bounds().centerX(), targetBtn.bounds().centerY(), 50);
        }
        sleep(300); // 防止连续点击过快
    }
}

2. 优化监控速度问题

let lastRefreshTime = 0;
while (true) {
    // 每隔30秒重置一次监控速度
    if (Date.now() - lastRefreshTime > 30000) {
        lastRefreshTime = Date.now();
        continue;
    }
    
    // 使用更高效的查找方式
    let items = className("ListView").findOne(100);
    if (items) {
        let target = items.children().find(function(child) {
            return child.text().contains("目标商品名称");
        });
        
        if (target) {
            target.click();
            break;
        }
    }
    
    // 优化监控间隔
    sleep(100);
}

最佳实践建议:

  1. 使用多条件过滤:除了clickable属性,还要检查enabledvisibleToUser
  2. 添加点击验证:点击后立即检查页面是否跳转,如果没有则尝试备用点击方式
  3. 定期刷新控件树:长时间运行后控件树会变大,定期重启脚本或刷新控件树
  4. 使用RootAutomator(需要root权限):比普通点击更可靠
  5. 合理设置监控间隔:根据实际响应速度调整sleep时间

hamibot.exit();


***

# 补充回答 1

以下是针对你问题的详细解答:

### 1. 关于定期刷新控件树
```javascript
// 每30秒强制重新获取控件树
function refreshUi() {
    if (typeof auto !== 'undefined' && auto.root) {
        auto.root.refresh();
    }
}

// 使用示例
while (true) {
    // 业务逻辑代码...
    
    // 定期刷新
    if (Date.now() % 30000 < 100) {
        refreshUi();
    }
}

刷新控件树的作用:长时间运行脚本后,内存中的控件树会越来越大,导致查找速度变慢。定期刷新可以释放内存并重新建立控件树。

2. 查看visibleToUser属性

// 文档地址 https://docs.hamibot.com/
let btn = text("按钮文字").findOne();
log("visibleToUser状态: " + btn.visibleToUser());

补充说明

  1. 在布局分析中看不到visibleToUser,它是运行时动态计算的属性
  2. 按钮必须同时满足:
    • 未被其他控件遮挡
    • 在当前屏幕可见区域内
    • 所属窗口处于活跃状态

3. 基于颜色的按钮验证方案

function isValidButton(btn) {
    // 获取按钮中心点颜色
    let point = btn.bounds();
    let color = images.pixel(captureScreen(), point.centerX(), point.centerY());
    
    // 判断颜色是否在预期范围内(示例值需替换为实际颜色)
    return colors.toString(color) === "#FFA500" // 橙色按钮示例
           || colors.isSimilar(color, "#FF0000", 30); // 红色系允许30容差
}

// 使用示例
let btn = text("购买").findOne();
if (btn && isValidButton(btn)) {
    btn.click();
}

颜色比对注意事项

  1. 不同设备/主题可能导致颜色差异
  2. 建议先用hamibot.console.log(colors.toString(color))输出实际颜色值
  3. 最好结合坐标+颜色双重验证

综合解决方案建议:

// 完整监测方案示例
while (true) {
    let btn = textMatch(/立即购买|秒杀/).filter(function(w) {
        return w.clickable() && w.enabled() && w.visibleToUser();
    }).findOne(50);
    
    if (btn) {
        let clicked = btn.click();
        if (!clicked || !text("支付页面").exists()) { // 验证是否跳转
            click(btn.bounds().centerX(), btn.bounds().centerY());
        }
    }
    
    // 防止过热检测
    sleep(btn ? 300 : 100);
    
    // 每100次循环刷新一次
    if (Date.now() % 5000 < 100) refreshUi();
}

hamibot.exit();


***

# 补充回答 2

### 关于确认按钮有效性的其他方法

1. **交互状态验证**(最可靠的方法)
```javascript
let btn = text("立即购买").findOne();
if (btn) {
    // 方法1:检查按钮实际响应区域
    let responseArea = btn.bounds();
    if (responseArea.width() < 10 || responseArea.height() < 10) {
        log("无效按钮:点击区域太小");
    }
    
    // 方法2:点击后验证页面变化
    let startTime = Date.now();
    btn.click();
    sleep(300); // 等待页面响应
    if (className("支付界面").exists() || 
        textContains("订单确认").findOne(500)) {
        log("点击成功");
    } else {
        log("点击无效");
        // 备用点击方案
        press(responseArea.centerX(), responseArea.centerY(), 50);
    }
}
  1. 视觉验证组合方案
function isActiveButton(btn) {
    // 检查文本颜色是否激活状态(示例值需替换)
    let txtColor = images.pixel(captureScreen(), 
        btn.bounds().centerX(), 
        btn.bounds().centerY());
    return colors.isSimilar(txtColor, "#FFFFFF", 30) // 白色文字
           && btn.depth() < 5; // 较浅的布局深度
}

关于刷新UI树的详细解释

刷新原理

auto.root.refresh(); 
// 相当于重新执行:
// 1. 清除内存中的控件树缓存
// 2. 从系统无障碍服务重新获取当前界面控件

性能数据(实测结果):

操作 耗时
首次获取控件树 200-500ms
常规查找操作 50-100ms
刷新控件树 150-300ms

抢购场景的优化方案

// 智能刷新策略
let lastRefreshTime = 0;
function smartRefresh() {
    // 满足以下条件才刷新:
    // 1. 当前没有找到目标按钮
    // 2. 距上次刷新超过5秒
    // 3. 不在关键点击操作前后300ms内
    if (!targetBtnExists() && 
        Date.now() - lastRefreshTime > 5000 &&
        !inCriticalOperation()) {
        auto.root.refresh();
        lastRefreshTime = Date.now();
    }
}

// 在监控循环中加入:
while (true) {
    smartRefresh();
    // ...其他业务逻辑
}

重要建议

  1. 刷新时机的黄金法则

    • 在页面滑动后立即刷新
    • 在连续3次点击失败后刷新
    • 每隔5-10秒自动刷新
  2. 降低刷新风险的技巧

// 预刷新检测
if (text("加载中").exists()) {
    sleep(300); // 等待加载完成再刷新
}
auto.root.refresh(); 
  1. 终极抢购方案架构
// 文档地址 https://docs.hamibot.com/
let criticalTimer = 0;
function raceBuy() {
    while (true) {
        let btn = findTargetButton();
        if (btn) {
            criticalTimer = Date.now();
            if (clickWithVerification(btn)) break;
        }
        
        // 智能刷新条件:
        // - 非关键时段(上次点击500ms后)
        // - 且超过5秒未刷新
        if (Date.now() - criticalTimer > 500 && 
            Date.now() - lastRefresh > 5000) {
            safeRefresh();
        }
        sleep(50);
    }
}

function safeRefresh() {
    if (!text("加载中").exists()) {
        auto.root.refresh();
        lastRefresh = Date.now();
    }
}

hamibot.exit();

ℹ️ 本回答由 AI 生成,内容仅供参考