首页Python【Python计算生态】p...

【Python计算生态】pywebview——桌面应用开发库

Python受欢迎的原因之一就是其计算生态丰富,据不完全统计,Python 目前为止有约13万+的第三方库。

本系列将会陆续整理分享一些有趣、有用的第三方库。

文章配套代码获取有以下两种途径:
  • 通过百度网盘获取:
链接:https://pan.baidu.com/s/1FSGLd7aI_UQlCQuovVHc_Q?pwd=mnsj 提取码:mnsj
  • 前往GitHub获取
https://github.com/returu/Python_Ecosystem





01
简介

pywebview 是一个用于桌面应用开发的跨平台 Python 第三方库,它允许开发者使用 HTMLCSS 和 JavaScript 来构建跨平台的桌面应用程序。通过 pywebview,你可以将网页技术与原生 GUI 窗口结合,使用 Python 处理后台逻辑,从而实现轻量级且功能丰富的桌面应用。
直接使用pip安装:
pip install pywebview
GitHub页面:
https://github.com/r0x0r/pywebview

02
使用

  • 基本用法:

pywebview 通过在不同操作系统上调用原生的 Web 渲染引擎来显示 HTML 内容。以下是一个简单的示例,展示如何使用 pywebview 创建一个包含 Web 视图的窗口:

import webview

def create_window():
    # 创建一个窗口,加载一个 URL
    window = webview.create_window('百度网页''https://www.baidu.com')
    # 启动 pywebview
    webview.start()

if __name__ == '__main__':
    create_window()

create_window 函数会创建一个新窗口,并返回一个 Window 对象实例。在调用 webview.start() 之前创建的窗口会在 GUI 循环启动时显示。在 GUI 循环启动后创建的窗口会立即显示。

运行代码后,会打开一个窗口,显示一个简单的 HTML 页面。

可以创建任意数量的窗口。所有打开的窗口都会以列表形式存储在 webview.windows 中,并且按照创建顺序排列。要获取当前活动(焦点所在)窗口的实例,可以使用 webview.active_window()

import webview
import time

def handler():
    time.sleep(3)  # 添加3秒的延迟
    print(f'当前有 {len(webview.windows)} 个窗口')
    print(f'活动窗口:{webview.active_window().title}')

first_window = webview.create_window('百度''https://www.baidu.com')
second_window = webview.create_window('必应''https://cn.bing.com/')
second_window.events.shown += handler
webview.start()

# 输出:
# 当前有 2 个窗口
# 活动窗口:百度
pywebview 库允许开发者从多个 Web 渲染器中进行选择。要更改使用的 Web 渲染器,需要在调用 start 函数时设置 gui 参数。start 函数是 pywebview 用于启动应用程序主循环的关键函数,而 gui 参数则用于指定要使用的 Web 渲染器。
  • 口对象:

Window 对象提供了许多函数和属性,用于与窗口进行交互。以下是一些常用的方法:

  • window.load_url(url):在窗口中加载一个新的 URL

  • window.load_html(content):直接将 HTML 内容加载到窗口中。

  • window.evaluate_js(script):在窗口中执行 JavaScript 代码,并返回结果。

  • window.toggle_fullscreen():在全屏和窗口模式之间切换窗口。

  • window.resize(width, height):将窗口调整为指定的宽度和高度。

  • window.move(x, y):将窗口移动到指定的 x 和 y 坐标。

  • window.hide():隐藏窗口。

  • window.show():如果窗口被隐藏,则显示窗口。

  • window.minimize():最小化窗口。

  • window.restore():如果窗口被最小化或最大化,则恢复窗口。

  • window.destroy():关闭窗口。


  • 后端逻辑:

  • webview.start 函数的基本功能

webview.start 函数的主要作用是启动图形用户界面(GUI)的事件循环。在桌面应用程序开发中,GUI 循环是一个持续运行的程序结构,它负责监听和处理各种用户交互事件,如鼠标点击、键盘输入等,并根据这些事件更新界面显示。
当调用 webview.start 时,程序会进入这个 GUI 循环,并且会阻止后续代码的执行,直到最后一个窗口被销毁。也就是说,在窗口关闭之前,webview.start 之后的代码不会被执行。
  • 后端逻辑的处理方式
由于 webview.start 会阻塞后续代码的执行,如果你的后端逻辑(如数据处理、网络请求等)直接写在 webview.start 之后,这些代码将无法在窗口显示期间运行。因此,为了让后端逻辑和 GUI 能够同时工作,你必须将后端逻辑放在一个单独的线程或进程中执行。
  • 利用 webview.start 启动后端逻辑
webview.start 函数提供了一种方便的方式来启动后端逻辑。你可以将后端逻辑封装成一个函数,然后将这个函数作为第一个参数传递给 webview.start,同时可以通过 *args 传递该函数所需的参数。
示例如下:
import webview

# 定义后端逻辑函数
def backend_logic(window):
    # 这里是后端逻辑代码
    print("Backend logic is running..."# 在控制台输出信息
    window.resize(1500, 1500) # 调整窗口大小
    window.evaluate_js('alert("欢迎关注:码农设计师")'# 执行 JavaScript 代码,用于在窗口弹出一个提示框

window = webview.create_window('My App', html='<h1>Hello, World!</h1>')
# 将后端逻辑函数传递给 webview.start
webview.start(backend_logic, window)
# 这一行之后的代码将在程序执行完成后运行
pass


  • 窗口事件:
pywebview 中的窗口对象有一系列与窗口操作和导航相关的事件,这些事件可以帮助开发者在特定的窗口状态变化时执行相应的代码逻辑,具体事件类型如下:
  • closed(关闭):当窗口关闭后触发该事件。通常用于执行一些资源清理、记录日志等操作,比如关闭数据库连接、保存用户的操作记录等。
  • closing(正在关闭):在窗口即将关闭时触发。开发者可以在这个事件中进行一些确认操作,例如询问用户是否保存未保存的工作,或者执行一些必要的预关闭处理。
  • loaded(已加载):当窗口中的网页内容加载完成后触发。可以利用这个事件来执行一些需要在页面加载完成后才能进行的操作,比如初始化页面上的一些 JavaScript 组件。
  • before_load(加载前):在窗口开始加载网页内容之前触发。可以在这个事件中对要加载的 URL 进行修改、添加额外的请求头信息等操作。
  • before_show(显示前):在窗口即将显示之前触发。可以在这个事件中对窗口的属性进行最后的调整,例如设置窗口的初始大小、位置等。
  • shown(已显示):窗口显示之后触发。可以在这个事件中执行一些需要在窗口可见时才能进行的操作,比如开始播放视频、启动动画等。
  • minimized(最小化):当窗口被最小化时触发。可以在这个事件中暂停一些不必要的后台任务,以节省系统资源。
  • maximized(最大化):窗口被最大化时触发。可以在这个事件中调整页面布局以适应最大化后的窗口大小。
  • restored(已恢复):当窗口从最小化或最大化状态恢复到正常大小时触发。可以在这个事件中恢复之前暂停的后台任务,或者重新调整页面布局。
  • resized(调整大小):窗口大小发生改变时触发。可以在这个事件中动态调整页面元素的大小和位置,以保证页面的布局在不同窗口大小下都能正常显示。
  • moved(移动):窗口位置发生移动时触发。可以在这个事件中记录窗口的新位置,或者根据窗口位置的变化执行一些特定的操作。
窗口事件可以通过 window.events 容器访问。使用 += 操作符订阅事件,使用 -= 取消订阅。
import webview

def on_closed():
    print("窗口已关闭")

def on_shown():
    print("窗口已显示")

def on_minimized():
    print("窗口已最小化")

def on_resized(width, height):
    print(f"窗口大小已改变,新的宽度为 {width},高度为 {height}")

def on_moved(x, y):
    print(f"窗口位置已移动,新的坐标为 ({x}, {y})")

if __name__ == '__main__':
    # 创建一个窗口,加载一个简单的 HTML 页面
    window = webview.create_window('事件展示窗口', html='<h1>欢迎查看窗口事件</h1>')

    # 订阅各种窗口事件
    window.events.closed += on_closed
    window.events.shown += on_shown
    window.events.minimized += on_minimized
    window.events.resized += on_resized
    window.events.moved += on_moved

    # 启动 pywebview
    webview.start()


  • Python与JavaScript交互:

pywebview 允许在 Python 和 JavaScript 之间进行双向通信。

  • Python 中运行 JavaScript

pywebview 提供了两种方式从 Python 中执行 JavaScript 代码:

1)、window.evaluate_js(code)方法:

通过该方法,可以在 Python 中运行 JavaScript 代码,返回 JavaScript 代码最后一行的执行结果。

如果JavaScript代码返回一个Promise,需要通过传递回调函数 来处理异步结果,即使用window.evaluate_js(code, callback)

如果 JavaScript 代码抛出错误,window.evaluate_js会抛出webview.errors.JavascriptException异常,开发者可以捕获该异常进行相应处理。

2)、window.run_js(code)方法

该方法也可用于执行 JavaScript 代码,但它不会返回执行结果,仅执行代码。

import webview

def run_js():
    # 示例 1:执行简单的 JavaScript 代码并获取返回值
    result = window.evaluate_js('2 + 2')
    print('Result of 2 + 2:', result)  # 输出:4

    # 示例 2:执行 JavaScript 函数并获取返回值
    js_code = """
    function multiply(a, b) {
        return a * b;
    }
    multiply(3, 4);
    "
""
    result = window.evaluate_js(js_code)
    print('Result of multiply(3, 4):', result)  # 输出:12

    # 示例 3:处理 JavaScript 中的 Promise
    js_promise = """
    new Promise((resolve) => {
        setTimeout(() => {
            resolve("
Hello from JavaScript Promise!");
        }, 1000);
    });
    "
""
    def callback(result):
        print('Result from Promise:', result)  # 输出:Hello from JavaScript Promise!
    window.evaluate_js(js_promise, callback)

if __name__ == '__main__':
    # 创建一个窗口并加载一个简单的 HTML 页面
    window = webview.create_window('Run JS from Python', html='<h1>Hello, pywebview!</h1>')
    webview.start(run_js)

运行上述代码后,你会看到一个窗口显示 Hello, pywebview!,同时在终端中输出以下内容:

Result of 2 + 2: 4
Result of multiply(3, 4): 12
Result from Promise: Hello from JavaScript Promise!


  • JavaScript 中运行 Python

为了从 JavaScript 中调用 Python 函数,需要将 Python 函数或类暴露给 JavaScript。
1)、暴露一个类
使用 webview.create_window(url, js_api=api_instance),将一个 Python 类的实例传递给 js_api 参数。
在 JavaScript 中,可以通过 window.pywebview.api.funcName 调用该类的方法。
2)、暴露单个函数
使用 window.expose(func),在运行时将单个 Python 函数暴露给 JavaScript
在 JavaScript 中,可以通过 window.pywebview.api.funcName 调用该函数。
import webview

# 定义一个类,用于封装供 JavaScript 调用的 Python 方法
class Api():
    # 定义一个方法,该方法接收一个参数 value
    def log(self, value):
        # 将传入的 value 参数打印到控制台
        print(value)
        

# 创建一个窗口
# 第一个参数是窗口的标题
# 第二个参数是 HTML 内容,这里创建了一个按钮,当按钮被点击时,
# 会调用 pywebview.api.log 方法,并传入字符串 "Hello, World!" 作为参数
# 第三个参数 js_api=Api() 表示将 Api 类的实例暴露给 JavaScript,
# 这样 JavaScript 就可以通过 pywebview.api 来调用 Api 类中的方法
webview.create_window("Test", html="<button onclick='pywebview.api.log("Hello, World!")'>Click me</button>", js_api=Api())

webview.start()

运行上述代码后,你会看到窗口中包含一个按钮。当点击按钮时,会触发 JavaScript 代码调用 Python 中的 log 方法,将 “Hello, World!” 打印到控制台。

  • HTTP 服务器:
  • 内置 HTTP 服务器:

pywebview 内部使用 bottle.py 作为 HTTP 服务器,用于提供静态文件服务。

当使用相对路径加载本地文件时(例如 ‘index.html’),pywebview 会自动启动一个 HTTP 服务器。这个 HTTP 服务器的根目录是当前工作目录(即运行 Python 脚本的目录),所有文件和子目录都可以通过 HTTP 访问。

如果需要启用 HTTPSSSL),可以在启动 webview 时设置 ssl=True

例如,加载本地的 HTML 文件(index.html),该文件实现了一个简单的功能,即通过点击按钮选择本地文件,并在网页上显示文件的文本内容:

import webview

window = webview.create_window('Local Files''index.html')  # 自动启动 HTTP 服务器
webview.start()

运行代码,点击窗口中的按钮选择本地文件,然后会在网页上显示文件的文本内容:


  • 外部 HTTP 服务器:
如果想使用一个外部的 WSGIWeb Server Gateway InterfaceWeb 服务器网关接口)兼容的 HTTP 服务器,可以将服务器应用对象作为 URL 传递给 webview.create_window 函数。
例如,使用 Flask 框架创建了一个 Web 应用:
from flask import Flask
import webview

# 创建一个 Flask 应用实例
app = Flask(__name__)

# 使用装饰器 @app.route 定义一个路由
# 当用户访问应用的根路径("/")时,会执行下面的函数
@app.route('/')
def index():
    return'<h1>Hello from Flask!</h1>'

# 将服务器应用对象作为 URL 传递给 webview.create_window 函数
window = webview.create_window('My App', app)
webview.start()

更多内容可以前往官方文档查看:

https://pywebview.flowrl.com/guide/

本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments