ultralight-py DOCSshabbywu/ultralight-py
DOCUMENTATION / APPCORE在 GitHub 查看源码 ↗

原生窗口与 Python API 注册表#

Application 使用 AppCore 提供系统字体、窗口布局、DPI、系统输入和 IME。 窗口中的页面仍是现有 View,资源加载、Session、对象代理和 Promise 桥接共用现有实现。

快速开始#

import asyncio
from ultralight_py import API, Application

with API("app") as api, Application() as app:

    @api.register
    async def hello(name):
        await asyncio.sleep(0)
        return f"你好,{name}"

    window = app.create_window(800, 520, title="Python 原生窗口")
    api.attach(window.view)
    window.view.load_html("""
        <input placeholder="输入中文">
        <script>
        app.hello('世界').then(value => document.body.append(value));
        </script>
    """)
    app.run()

Application 必须在首次创建 Runtime 之前创建。app.runtime 是现有 Runtime 类型, 后续 Runtime() 返回同一个实例。引擎关闭后不能重建。 Application 接受 assets_root、resource_loader、cache_path,参数含义与 Runtime 相同; app_name 和 developer_name 默认 ultralight-py,供 AppCore 默认存储目录使用。

完整示例使用 Python 虚拟资源、Session、装饰器和异步函数:

python examples/appcore.py
python examples/appcore.py --smoke
python examples/appcore.py --cpu --smoke

窗口与 View#

app.create_window(width, height, *, title="", session=None, view=None, transparent=False, resizable=True, fullscreen=False) 创建窗口。 尺寸为有限正数,单位是逻辑像素。默认创建一个填满窗口的 View; 显式 Session 必须属于 app.runtime。使用已有 View 时传入 view=..., 该 View 必须尚未托管且属于应用 Runtime,不能同时指定 Session。 已有 View 保留其渲染及字体配置,Panel 负责后续布局和 DPI 更新。

窗口提供 view、closed、width/height、device_width/device_height、 device_scale 和可修改的 title。on("resized", callback) 接收逻辑尺寸元组, on("closed", callback) 接收 None;返回现有 Subscription。回调同步执行,异常转交 Runtime 错误处理器。关闭通知执行前,窗口 View 与相应等待已经关闭。

新建窗口 View 跟随 AppCore 渲染配置;force_cpu_renderer=True 使用 CPU 路径。 加速 View 的 copy_pixels() 抛 Unsupported;app.runtime.create_view() 仍创建 CPU 离屏 View。 Window 托管 View 和 Python 包装,丢弃外部 View 引用不会关闭页面。 系统输入由 AppCore 自动转发,焦点经由 Panel;IME 使用 AppCore 的编辑监听器。

注册与恢复#

API(namespace) 使用一个 ASCII JavaScript 标识符作为全局命名空间;Python、ul 和 ultralight 保留。注册项名称也必须是 ASCII JavaScript 标识符。

接口 行为
register(function, *, name=None) 使用函数名或显式名称注册,返回原函数
@api.register、@api.register(name="save") 装饰器形式,支持同步和异步可调用对象
register_object(name, instance, *, members=None) 复用现有 Python 对象代理与成员限制
unregister(name) 删除定义,撤销各 View 当前文档中的旧代理;不存在时无操作
attach(view) 加载前附着,或立即安装到当前文档;同一 API 重复附着无操作
detach(view) 立即撤销该 View 的代理并停止导航恢复
close()、closed 撤销全部附着,释放注册定义;关闭幂等

注册表可以在 Runtime 创建前定义,也可以附着到多个 View。同一 View 不允许两个注册表 使用相同命名空间,已有页面全局名称冲突时附着报错。新增或替换定义立即更新所有附着 View, 旧绑定及其嵌套代理、方法与异步投递被撤销。

内部主框架 window_ready 在页面首行脚本之前安装注册表,再通知用户回调。 主框架导航撤销旧文档会话,并按最新定义恢复新文档;用户更换页面回调不会移除重放。 只向主框架注入,附着持续覆盖后续导航;需要停止暴露时显式调用 detach()。 每个注册项在每个文档中拥有独立代理会话,其对象、容器和 asyncio 语义见 对象桥接。 View.bind_object/bind_function 仍用于当前文档的临时导出。

View 关闭或最后一次分离 不清空注册定义。API 持有对象直到注销、替换或关闭; 使用 with API(...) 可以及时释放这些引用。View 持有附着的原生注册表,注册表弱引用 View。

循环和关闭#

app.run() 在主线程创建 asyncio 循环并持续驱动窗口;已有循环使用 await app.run_async(update_interval=1/60)。间隔必须为有限正数。 AppCore 每轮处理系统事件、更新、显示刷新和渲染,同时执行异步投递、条件重检与清理。 没有页面等待时仍持续驱动,页面动画和系统输入继续工作。

run_once() 供外部宿主手动步进,返回应用是否仍存活;宿主自行推进 asyncio。 自动运行时禁止另行步进,步进和运行入口均禁止重入。 AppCore Runtime 的 update/refresh_display/render、离屏 asyncio 的 install() 及 ScriptDriver.auto() 抛 Unsupported。需要脚本接口时在应用循环中使用 ScriptDriver(app.runtime),它等待应用帧通知,不启动第二个引擎循环。

关闭一个窗口撤销其文档代理、JS Promise 监听、页面等待和桥接投递, 其余窗口继续运行。最后一个窗口关闭后,应用退出并关闭显式 Session、资源加载与 Runtime。 单独关闭 View 或 Session 强制关闭只移除相应 Panel,窗口继续存活。 关闭 Runtime 或 Application 会关闭全部窗口;操作幂等,旧 JS 句柄报 PageGone。

run_async() 的取消或驱动异常也关闭应用,并传播原异常;调用方 asyncio 循环保持运行。 桥接请求取消自己创建的 Python Task,外部 Task/Future 只解除监听。 取消为协作式请求,任务需正常处理取消。文档引用和延迟 Python 引用在主线程清理, 独立 API 的注册定义仍遵循上述显式关闭规则。

平台验收#

发行配置包含 Windows x64、Linux x64 和 macOS ARM64 的 AppCore 运行库。 macOS 原生桌面测试覆盖 macOS ARM64 的默认/CPU 渲染、DPI 与像素尺寸、资源加载、 多窗口、Session、异步驱动和关闭路径。Windows/Linux 桌面交互需在对应系统验收。

运行交互示例可验证中文系统字体、窗口拖动与尺寸调整、跨显示器 DPI, 以及中文预编辑、候选框位置、复制粘贴和焦点切换。真实跨屏 DPI 与输入法组合 需要本机交互验证,自动测试不模拟输入法。

搜索文档

输入关键词搜索 API 与使用指南

    ↑ ↓ 选择 · Enter 打开 · Esc 关闭