一. 前言
在这一篇里面会引入两个知识点 :
- Apache ECharts : 一款 JavaScript 的可视化图表图 ,功能齐全 ,用法简单
- PyQt6-WebEngine : PyQt6 的扩展模块,它基于 Qt WebEngine,允许在 PyQt6 应用程序中嵌入和显示现代网页内容
先来看一下 ECharts 支持的图表有多少
再来看看 WebEngine 的简单原理
WebEngine 是基于 Chromium 开发 ,通过集成 Chromium 到 QT 框架中 ,使 WebEngine 具有了浏览器的功能。
但是要注意 ,由于打入了 Chromium 的相关资源和文件 ,会导致 PyQt 导打包的文件明显变大。
所以在打包过程中 ,需要优化文件大小等工作(这个后续再看)。
二. PyQt 集成 Web-Engine
2.1 基础入门使用
// 安装 Web-WebEngine
pip install PyQt6 PyQt6-WebEngine
// 相关代码 :
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtCore import QUrl
class WebBrowser(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('PyQt6 百度一下')
self.setGeometry(100, 100, 1200, 800)
# 创建 QWebEngineView
self.browser = QWebEngineView()
# 加载 URL
self.browser.setUrl(QUrl("https://www.baidu.com/"))
# 将浏览器设置为主窗口的小部件
self.setCentralWidget(self.browser)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = WebBrowser()
window.show()
sys.exit(app.exec())
- 在这个里面实现了基础的浏览器功能 ,让 PyQT 应用里面可以展示Web端的页面
直接展示 HTML 脚本
html_content = '''
<!DOCTYPE html>
<html>
<head>
<title>PyQt6 WebEngine Example</title>
</head>
<body>
<p>在 PyQt6 App 中展示一段 HTML 文本</p>
</body>
</html>
'''
# 加载 HTML 内容
self.browser.setHtml(html_content)
- 还可以通过传入一段 HTML 脚本 + setHtml 方法 ,展示 HTML 文本
- 但是这样并不满足我们的复杂需求 ,我们需要一定的 JS 的能力
2.2 运行相关的 Java Script
第一种方式 : 把 JavaScript 代码写在脚本文件中
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget
from PyQt6.QtWebEngineWidgets import QWebEngineView
class WebBrowser(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('PyQt6 JS 代码')
self.setGeometry(100, 100, 1200, 800)
# 创建主布局
self.layout = QVBoxLayout()
# 创建浏览器
self.browser = QWebEngineView()
# HTML 内容
html_content = '''
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Example</title>
</head>
<body>
<h1 id="title">这是一段文本!</h1>
<button onclick="changeTitle()">Change Title</button>
<script>
function changeTitle() {
document.getElementById("title").innerText = "我点了一下,所以它变了";
}
</script>
</body>
</html>
'''
# 加载 HTML
self.browser.setHtml(html_content)
self.setCentralWidget(self.browser)
// 省略 main 方法
- 把 HTML 相关内容聚合在自己的 HTML 文件里面 ,然后让它的模块内部流转是 一种比较好的隔离方式
- 但是 ,在 PyQT 上面我们无法进行完全的隔离 ,因为数据要进行流转 ,功能要回调 ,这样就要进行耦合交互
方式二 : Python 和 Web 交互进行耦合
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget
from PyQt6.QtWebEngineWidgets import QWebEngineView
class WebBrowser(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('JavaScript 脚本的使用')
self.setGeometry(100, 100, 1200, 800)
# 创建主布局
self.layout = QVBoxLayout()
# 创建浏览器
self.browser = QWebEngineView()
# HTML 内容
html_content = '''
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Example</title>
</head>
<body>
<h1 id="title">Hello, World!</h1>
</body>
</html>
'''
# 加载 HTML
self.browser.setHtml(html_content)
# 添加按钮用于执行 JavaScript
self.button = QPushButton('点击修改')
self.button.clicked.connect(self.run_js)
# 布局 (此处添加了按钮和展示窗)
self.layout.addWidget(self.browser)
self.layout.addWidget(self.button)
# 创建中央小部件并设置布局
container = QWidget()
container.setLayout(self.layout)
self.setCentralWidget(container)
def run_js(self):
# 运行 JavaScript 并获取结果
# 前面是要执行的 JS 脚本 ,后面是回调的方法
self.browser.page().runJavaScript(
'document.getElementById("title").innerText="点了一下最下面的按钮"', self.js_callback)
def js_callback(self, result):
print(f"JavaScript Result: {result}")
// 省略 main 方法
在这个代码里面 ,就实现了 PyQT 的工具组件和 JS / HTML 的交互关系
2.3 加载 HTML 文件
- 不过 ,直接把 HTML 内容写在代码里面是很不合理的 ,所以
可以通过引入 HTML 文件进行更轻量化的处理
# 加载本地 HTML 文件
current_dir = os.path.dirname(os.path.abspath(__file__))
local_file_path = os.path.join(current_dir, 'web.html')
local_url = QUrl.fromLocalFile(local_file_path)
self.browser.setUrl(local_url)
# 将浏览器设置为主窗口的小部件
self.setCentralWidget(self.browser)
- 这种方式也是比较理想的 HTML 集成方式
三. 集成 EChats
上面学习完了 WebEngine , 剩下就是 集成 Echats 了, 先来一个简易版的 :
基础简易版 :
代码就不贴了 ,我这里直接使用的本地JS文件 :
- S1 : 下载 echats 的代码 Echats.main.js
- S2 : 准备好 HTML 文件
- S3 : 通过注入 HTML 的方式进行注入
从外部导入数据
❓ 为了让 Data 数据的导入更加方便 ,所以数据源要在 Python 代码中生成 ,并且导入到 HTML 文件中。
- 由于
Echats 的良好支持
,可以通过 JSON 文件进行数据的传递 - 这里从一个 data.json 文件中读取到数据格式 ,通过 runJavaScript 运行 JS 脚本
- 以下是完整代码 👇👇👇
import sys
import os
import json
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtCore import QUrl
class WebBrowser(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('PyQt6 WebEngine JavaScript Example')
self.setGeometry(100, 100, 1200, 800)
# 创建主布局
self.layout = QVBoxLayout()
# 创建浏览器
self.browser = QWebEngineView()
# 获取当前目录的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
local_file_path = os.path.join(current_dir, 'no_data.html')
url = QUrl.fromLocalFile(local_file_path)
self.browser.setUrl(url)
# 添加按钮用于执行 JavaScript
self.button = QPushButton('点击修改')
self.button.clicked.connect(self.run_js)
# 布局
self.layout.addWidget(self.browser)
self.layout.addWidget(self.button)
# 创建中央小部件并设置布局
container = QWidget()
container.setLayout(self.layout)
self.setCentralWidget(container)
# 此处为了方便展示 ,把数据先存到了data.json 文件中
# 在复杂的场景中 ,可以通过更多其他的方式生成 json 数据
def run_js(self):
# 在 EChartsWindow 类中加载完 HTML 后调用
data_str = self.load_json_data('data.json')
print(f"JavaScript Result: {data_str}")
js_code = f'initChart({data_str});'
self.browser.page().runJavaScript(js_code)
# 回调函数
def js_callback(self, result):
print(f"JavaScript Result: {result}")
# 加载本地的 JSON 文件
def load_json_data(self, filename):
current_directory = os.path.dirname(os.path.abspath(__file__))
json_file_path = os.path.join(current_directory, filename)
with open(json_file_path, 'r', encoding='utf-8') as json_file:
data = json.load(json_file)
return data
if __name__ == "__main__":
app = QApplication(sys.argv)
window = WebBrowser()
window.show()
sys.exit(app.exec())
data.json + html
{
"title": {
"text": "ECharts 入门示例"
},
"tooltip": {},
"legend": {
"data": ["销量"]
},
"xAxis": {
"data": ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"
]
},
"yAxis": {},
"series": [
{
"name": "销量",
"type": "bar",
"data": [
5,
20,
36,
10,
10,
20
]
}
]
}
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="utf-8">
<title>ECharts Example</title>
<!-- 引入 ECharts -->
<script src="echarts.min.js"></script>
<script type="text/javascript">
if (typeof echarts === 'undefined') {
alert('ECharts 加载失败');
}
</script>
</head>
<body style="height: 100%; margin: 0">
<div id="main" style="height: 100%"></div>
<script type="text/javascript">
function initChart(data) {
// 基于准备好的 DOM,初始化 echarts 实例
myChart = echarts.init(document.getElementById('main'));
myChart.setOption(data);
}
</script>
</body>
</html>
- 这里点击后 ,数据就自然生成了。👇👇👇
复杂的操作就不展示了
,能到这一步后面都唰唰唰的上
总结
使用感受 :
- 论美观 ,JS 库还是要比 Python 的库强太多了
- 上手难度不高 ,花1-2个小时就可以创建复杂的图表
- 性能还不错 ,展示的很快 ,用法也很灵活
🎉🎉🎉❤️❤️❤️ 祝大家国庆节快乐 !!!
最后的最后 ❤️❤️❤️👇👇👇
- 👈 欢迎关注 ,超200篇优质文章,未来持续高质量输出 🎉🎉
- 🔥🔥🔥 系列文章集合,高并发,源码应有尽有 👍👍
- 走过路过不要错过 ,知识无价还不收钱 ❗❗