A lightweight and powerful WebView2 widget for Python Qt (PySide/PyQt) with a seamless JS bridge.
Project description
QtWebView2
| English | 简体中文 |
📖 Introduction
QtWebView2 is a Python wrapper for embedding Microsoft's WebView2 into a Qt application, complete with a powerful JS bridge. It is built upon QtPy and Python.NET.
Disclaimer: This project is currently in a beta stage. The API may change in future updates, but early adopters and feedback are welcome!
✨ Features
- 🎸 Lightweight Integration: Directly wraps the native WebView2 control using Python.NET, resulting in a minimal increase in your application's package size compared to solutions like
QWebEngineView. - 🎻 Powerful JS Bridge: Provides a robust JS bridge solution for seamless two-way communication between Python and JavaScript, using modern JS features like
Promiseandasync/await. - 🎷 Thread-Safe: Most API calls are carefully designed to be thread-safe, ensuring stability and safety in multi-threaded environments by leveraging Qt's signal and slot mechanism.
- 🎺 Out-of-the-Box: Comes with rich configuration options and robust error handling, allowing you to get started quickly with minimal setup.
- 🎼 QtPy Support: Built on QtPy, making it compatible with both PyQt6 and PySide6.
⬇️ Installation
⚠️ Note: This library currently supports the Windows platform only.
python -m pip install qtwebview2
Alternatively, you can install from the source:
git clone https://github.com/xiaosuyyds/QtWebView2.git
cd QtWebView2
python -m pip install .
Important! The corresponding Qt backend is not installed as a dependency. You need to install your preferred backend (e.g., PySide6 or PyQt6) yourself.
🧑💻 Usage
Here is a complete example demonstrating the core features.
import sys
from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
from qtpy.QtCore import Slot, QCoreApplication
from qtwebview2 import QtWebView2Widget, DictJsBridge
# Set an application name for the user data folder
QCoreApplication.setApplicationName("QtWebView2-Demo")
# 1. Initialize the application and window
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("QtWebView2 - JS Bridge Demo")
window.setGeometry(100, 100, 800, 600)
layout = QVBoxLayout(window)
# 2. Create an instance of the JS bridge
js_bridge = DictJsBridge()
# 3. Create the WebView2 widget and inject the JS bridge
webview = QtWebView2Widget(parent=window, js_apis=js_bridge)
layout.addWidget(webview)
# 4. (JS -> Python) Define a Python function and expose it to JavaScript
@js_bridge.bind_js_api_func
def get_user_os():
"""This Python function will be callable from JavaScript."""
print(f"Python function 'get_user_os' was called from JavaScript!")
return sys.platform
# 5. Define HTML content that includes JavaScript to call the Python function
html_content = """
<!DOCTYPE html>
<html>
<head><title>JS Bridge Test</title></head>
<body style="font-family: sans-serif; text-align: center; background-color: #f0f0f0;">
<h1>QtWebView2 JS Bridge Demo</h1>
<button onclick="callPython()">Click me to call Python!</button>
<p>Result from Python: <b id="result">...</b></p>
<script>
async function callPython() {
try {
// Use async/await to call the Python function and get the result
const os = await window.qtwebview2.api.get_user_os();
document.getElementById('result').textContent = os;
} catch (e) {
document.getElementById('result').textContent = 'Error: ' + e;
}
}
</script>
</body>
</html>
"""
webview.load_html(html_content)
# 6. (Python -> JS) Connect to a signal and execute JavaScript when it's emitted
@Slot()
def on_dom_loaded():
"""This function is called when the web page's DOM is fully loaded."""
print(f"DOM content loaded. Executing JS from Python...")
# You can also execute JavaScript from Python
webview.evaluate_js("""(function() {
const new_element = document.createElement('h2');
new_element.textContent = 'Hello from Python!';
document.body.appendChild(new_element);
})()""")
webview.bridge.domContentLoaded.connect(on_dom_loaded)
window.show()
sys.exit(app.exec())
License
Copyright (c) 2025 Xiaosu.
Distributed under the terms of the Mozilla Public License Version 2.0.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qtwebview2-0.1.1.tar.gz.
File metadata
- Download URL: qtwebview2-0.1.1.tar.gz
- Upload date:
- Size: 382.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9118ecd12ecc05dcc87c08d1f09812fa1ba528a550b8587b57c72cc5ab68dca9
|
|
| MD5 |
85c05e3dd7e000771f21b9bcebfe95b6
|
|
| BLAKE2b-256 |
0e9a37c75c69e955d2b4270b5103e0c84e625e5b1c7884ddee9f1fa52cd8e6fd
|
Provenance
The following attestation bundles were made for qtwebview2-0.1.1.tar.gz:
Publisher:
publish-to-pypi.yml on xiaosuyyds/QtWebView2
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qtwebview2-0.1.1.tar.gz -
Subject digest:
9118ecd12ecc05dcc87c08d1f09812fa1ba528a550b8587b57c72cc5ab68dca9 - Sigstore transparency entry: 637607277
- Sigstore integration time:
-
Permalink:
xiaosuyyds/QtWebView2@8b6baec09c55675ef403dd5048a812f665c7a113 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/xiaosuyyds
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@8b6baec09c55675ef403dd5048a812f665c7a113 -
Trigger Event:
release
-
Statement type:
File details
Details for the file qtwebview2-0.1.1-py3-none-any.whl.
File metadata
- Download URL: qtwebview2-0.1.1-py3-none-any.whl
- Upload date:
- Size: 380.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f9bb8599355c6602be219ec96bda049eaecddc757bae1964c03a50a6f1124819
|
|
| MD5 |
033dd472280336f38fddef8f0aafe8cd
|
|
| BLAKE2b-256 |
c236b81b5c58f6273cbfec5156da7c8006df9932f268a0bb3d733f0c8e05d0de
|
Provenance
The following attestation bundles were made for qtwebview2-0.1.1-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on xiaosuyyds/QtWebView2
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qtwebview2-0.1.1-py3-none-any.whl -
Subject digest:
f9bb8599355c6602be219ec96bda049eaecddc757bae1964c03a50a6f1124819 - Sigstore transparency entry: 637607278
- Sigstore integration time:
-
Permalink:
xiaosuyyds/QtWebView2@8b6baec09c55675ef403dd5048a812f665c7a113 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/xiaosuyyds
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@8b6baec09c55675ef403dd5048a812f665c7a113 -
Trigger Event:
release
-
Statement type: