CefPython中SendMouseWheelEvent后续页面加载失效问题求助
问题描述
使用CEF Python 66.1调用SendMouseWheelEvent向浏览器传递鼠标滚动指令时,仅在首次页面加载时生效,后续页面加载后无法正常工作,除非用真实鼠标手动滚动一次。
测试脚本说明:
- 测试1:调用JS的
scrollBy方法,每次页面加载后都能正常滚动 - 测试2:调用
SendMouseWheelEvent,仅首次页面加载时有效
测试代码(errorrep.py):
from cefpython3 import cefpython as cef import time from threading import Thread import errorrep mybrowser = None def main(): cef.Initialize() browser = cef.CreateBrowserSync(url="https://stackoverflow.com/") browser.SetClientHandler(LoadHandler()) errorrep.mybrowser = browser cef.MessageLoop() del browser cef.Shutdown() class LoadHandler(object): def OnLoadingStateChange(self, browser, is_loading, **_): if not is_loading: Thread(target=test).start() def test(): print("Page loading is complete!") for i in range(5): print('scrolling') # test 1 errorrep.mybrowser.ExecuteJavascript(jsCode="""scrollBy(0,25)""") # test 2 # errorrep.mybrowser.SendMouseWheelEvent(0,0,0,-120, cef.EVENTFLAG_NONE) time.sleep(1) print('opening new page, clicking on the logo link') errorrep.mybrowser.ExecuteJavascript(jsCode="""document.getElementsByClassName('s-topbar--logo js-gps-track')[0].click();""") if __name__ == '__main__': main()
解决方案
1. 确保浏览器获得输入焦点
后续页面加载后,浏览器可能失去输入焦点,导致模拟的滚轮事件不被响应。发送滚轮事件前先调用SetFocus(True)让浏览器获得焦点:
errorrep.mybrowser.SetFocus(True) errorrep.mybrowser.SendMouseWheelEvent(0,0,0,-120, cef.EVENTFLAG_NONE)
2. 在CEF主线程执行事件发送
CEF的大部分API调用需要在消息循环所在的主线程执行,当前用Thread启动测试函数存在线程安全问题。改用cef.PostTask将滚轮事件发送逻辑放到主线程执行:
def send_wheel_event(browser): browser.SetFocus(True) browser.SendMouseWheelEvent(0, 0, 0, -120, cef.EVENTFLAG_NONE) # 在test函数中替换原测试2代码 cef.PostTask(cef.TID_UI, send_wheel_event, errorrep.mybrowser)
3. 修正滚轮事件的坐标参数
SendMouseWheelEvent的前两个参数是鼠标坐标,需确保坐标落在页面可视区域内。可以获取浏览器窗口尺寸,传入中间位置坐标:
def send_wheel_event(browser): browser.SetFocus(True) # 获取浏览器客户端区域尺寸 window_rect = browser.GetWindowInfo().GetClientRect() x = (window_rect['right'] - window_rect['left']) // 2 y = (window_rect['bottom'] - window_rect['top']) // 2 browser.SendMouseWheelEvent(x, y, 0, -120, cef.EVENTFLAG_NONE)
完整修正后的test函数示例
def test(): print("Page loading is complete!") for i in range(5): print('scrolling') # 替换test1为test2的修正逻辑 def send_wheel(): errorrep.mybrowser.SetFocus(True) window_rect = errorrep.mybrowser.GetWindowInfo().GetClientRect() x = (window_rect['right'] - window_rect['left']) // 2 y = (window_rect['bottom'] - window_rect['top']) // 2 errorrep.mybrowser.SendMouseWheelEvent(x, y, 0, -120, cef.EVENTFLAG_NONE) cef.PostTask(cef.TID_UI, send_wheel) time.sleep(1) print('opening new page, clicking on the logo link') errorrep.mybrowser.ExecuteJavascript(jsCode="""document.getElementsByClassName('s-topbar--logo js-gps-track')[0].click();""")
内容的提问来源于stack exchange,提问作者Flora42
相关产品推荐
相关产品推荐

