这篇文章是此前
pywebview系列文章的进阶篇 - 基于pywebview操作前端界面元素。
为什么会有这个场景呢,因为有些使用场景下,使用 pywebview 开发时,前端无法调用到后端的 API,而这个时候只能由后端直接来操作前端页面。解释起来有点难,下面结合我实际的开发经验来解释吧。
基于官方文档 - Javascript–Python 桥梁 | pywebview 中文文档[1],我们可以知道:在 pywebview 框架中,实现 Javascript 和 Python 间交互,主要依赖于 window 对象。
# python调用js-api方式:window.evaluate_js(code, callback=None)def evaluate_js(window):try:result = window.evaluate_js('syntaxerror#$%#$')except JavascriptException as e:print('JavaScript 异常发生: ', e)if __name__ == '__main__':window = webview.create_window('Evaluate JavaScript', html='<html><body></body></html>')webview.start(evaluate_js, window)# python封装成js-api方式:pywebview.api.method_nameif __name__ == '__main__':api = Api()window = webview.create_window('JS 接口 示例', html=html, js_api=api)webview.start()
但是这里有个问题,你很难通过这两种方式在前端构建监听事件来直接操作 window 对象或其他 pywebview 框架本身的 api。
以我最近开发 todo-list 应用为例,有个场景:实现应用窗口在桌面置顶功能。
而目前查询 pywebview 框架官网的 api,可以使用 window.on_top 设置 True 或 False 来实现。最初想的很简单,就前端触发点击「置顶按钮」事件后,调用 window.on_top 就实现置顶了,再次调用就取消执行。

而实践发现:基于上述两种方式,操作不了。
通过方式一是 Python 操作前端 Javascript,你没法在 Javascript 中调用 pywebview 的 api;
通过方式二是 Python 封装成 js-api ,但问题是封装的 js-api 是调用 webview.create_window 方法传入的,这个方法执行完才会创建 window 对象,也就是你创建 window 的时候,就必须初始化所有的 api 。所以你做不到封装的 js-api 中去调用 window 对象,因为还没创建。
因为这个问题,昨天苦恼了一整天。尝试用 AI 实现,直接循环调用 window 对象,页面都响应不了了。
好在 pywebview 官方文档很全,今早查阅发现 pywebview 本身也可以操作前端 dom 对象,而不需要依赖 Javascript - DOM 操作示例 | pywebview 中文文档[2] 。
也就是置顶功能,可以这样玩:通过 python 监听前端「置顶按钮」的点击事件,如果点击了,直接通过 python 调用 window.on_top 就可以了,完全不依赖前端 Javascript 。事实证明确实可行,下述是简化的代码示例:
import webviewfrom backend.api.todo_api import TodoApiwindow = Nonewindow_on_top = Falsedef start_app(window):def bind(window):# 直接获取「置顶按钮」button = window.dom.get_element('#pin-top-btn')button.events.click += click_handler# 「置顶按钮」点击事件def click_handler(e):global window_on_topwindow_on_top = not window_on_topapp_logger.info("TodoList 应用当前是否设置置顶:" + str(window_on_top))window.on_top = window_on_top# 创建API实例api = TodoApi()# 获取前端文件路径frontend_path = get_resource_path('frontend/index.html')window = webview.create_window('Todo List App',frontend_path,js_api=api,width=1000,height=700,resizable=True)webview.start(bind, window, ssl=True, debug=True)if __name__ == '__main__':start_app(window)
好啦,今天的技术分享就到这里了,更多有关 python 直接操作前端页面元素的,可以查看官网相关 API:API | pywebview 中文文档[3]
如果觉得本文对你有所帮助,欢迎三连哦!
Javascript–Python 桥梁 | pywebview 中文文档: https://pywebview.idepy.com/guide/interdomain.html
[2]DOM 操作示例 | pywebview 中文文档: https://pywebview.idepy.com/examples/dom_manipulation.html
[3]API | pywebview 中文文档: https://pywebview.idepy.com/guide/api.html#webview-dom