77 lines
3.0 KiB
Python
77 lines
3.0 KiB
Python
import webview
|
||
import threading
|
||
import time,os
|
||
|
||
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||
|
||
# ---------------------- 1. 定义供 JS 调用的 Python 函数 ----------------------
|
||
class Api:
|
||
"""暴露给 JS 的 Python 接口类(所有方法都会被 JS 访问)"""
|
||
def __init__(self):
|
||
self.window = None # 保存窗口实例,用于 Python 主动调用 JS
|
||
|
||
def set_window(self, window):
|
||
"""初始化时绑定窗口实例"""
|
||
self.window = window
|
||
|
||
def python_hello(self, name):
|
||
"""JS 调用的同步函数:接收参数,返回结果"""
|
||
print(f"[Python] 收到 JS 调用,参数:{name}")
|
||
return f"Hello {name}! 这是 Python 返回的消息"
|
||
|
||
def python_async_task(self, duration):
|
||
"""JS 调用的异步函数:模拟耗时任务(不阻塞前端)"""
|
||
def async_task():
|
||
print(f"[Python] 开始异步任务,耗时 {duration} 秒")
|
||
time.sleep(duration)
|
||
# 异步任务完成后,主动调用 JS 函数通知结果
|
||
self.window.evaluate_js(f'js_receive_python_msg("异步任务完成!耗时 {duration} 秒")')
|
||
print(f"[Python] 异步任务结束")
|
||
|
||
# 启动子线程执行异步任务,避免阻塞 UI
|
||
threading.Thread(target=async_task, daemon=True).start()
|
||
return "异步任务已启动,请等待结果通知"
|
||
|
||
def python_close_window(self):
|
||
"""JS 调用关闭窗口"""
|
||
print("[Python] 收到关闭窗口请求")
|
||
self.window.destroy()
|
||
|
||
# ---------------------- 2. Python 主动调用 JS 函数 ----------------------
|
||
def python_call_js_periodically(window):
|
||
"""Python 定时调用 JS 函数(模拟主动推送数据)"""
|
||
count = 0
|
||
while window.is_alive():
|
||
count += 1
|
||
# 执行 JS 函数,传递参数
|
||
window.evaluate_js(f'js_receive_python_msg("Python 主动推送:第 {count} 条消息")')
|
||
time.sleep(3) # 每 3 秒推送一次
|
||
if count >= 5:
|
||
break
|
||
|
||
# ---------------------- 3. 启动窗口 ----------------------
|
||
if __name__ == "__main__":
|
||
# 创建 API 实例
|
||
api = Api()
|
||
|
||
# 加载本地 HTML 文件(也可加载远程 URL:url="https://xxx.com")
|
||
window = webview.create_window(
|
||
title="PyWebView 双向通信示例",
|
||
# url="app_JsToPy.html", # 前端页面路径
|
||
url=f"file:///{CURRENT_DIR}/app_JsToPy.html",
|
||
resizable=True,
|
||
js_api=api # 关键:暴露 Python API 给 JS
|
||
)
|
||
|
||
# 绑定窗口实例到 API(供异步任务调用 JS)
|
||
api.set_window(window)
|
||
|
||
# 启动 Python 主动调用 JS 的线程(非阻塞)
|
||
threading.Thread(target=python_call_js_periodically, args=(window,), daemon=True).start()
|
||
|
||
# 运行窗口(阻塞主线程)
|
||
webview.start(
|
||
private_mode=False, # WebRTC必需关闭私有模式
|
||
debug=True, # 开发环境开启调试,生产环境关闭
|
||
http_server=True # 启用内置 HTTP 服务器(加载本地 HTML 必需)
|
||
) |