这篇文章是此前
pywebview系列文章的进阶篇 - 基于pywebview操作前端界面元素。
系列文章:
Pywebview:Web技术构建桌面应用的最佳选择
PyWebView 移动端适配踩坑实录
使用场景说明
为什么会有这个场景呢,因为有些使用场景下,使用 pywebview 开发时,前端无法调用到后端的 API,而这个时候只能由后端直接来操作前端页面。解释起来有点难,下面结合我实际的开发经验来解释吧。
基于官方文档 - Javascript--Python桥梁 | pywebview中文文档,我们可以知道:在 pywebview 框架中,实现 Javascript 和 Python 间交互,主要依赖于 window 对象。
python
# 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_name
if __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中文文档 。
也就是置顶功能,可以这样玩:通过 python 监听前端「置顶按钮」的点击事件,如果点击了,直接通过 python 调用 window.on_top 就可以了,完全不依赖前端 Javascript 。事实证明确实可行,下述是简化的代码示例:
python
import webview
from backend.api.todo_api import TodoApi
window = None
window_on_top = False
def 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_top
window_on_top = not window_on_top
app_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中文文档
如果觉得本文对你有所帮助,欢迎三连哦!