[Python自学] PyQT5-Web控件、与JavaScript交互
<h2>一、使用WEB控件打开网页</h2><p>要使用PyQt5的WebEngine,需要安装PyQtWebEngine(pyqt5 5.11版本之前可以直接from PyQt5.QtWebEngineWidgets import *)</p>
<div class="cnblogs_code">
<pre>pip install PyQtWebEngine</pre>
</div>
<p>Demo:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> sys
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 使用调色板等</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtCore <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Qt, QUrl
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtGui <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QIcon
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 导入QT,其中包含一些常量,例如颜色等</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 导入常用组件</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QApplication, QMainWindow, QTextEdit
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QMdiArea, QMdiSubWindow
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWebEngineWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QWebEnginePage, QWebEngineView
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> DemoWin(QMainWindow):
count </span>=<span style="color: rgba(0, 0, 0, 1)"> 0
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self):
super(DemoWin, self).</span><span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">()
self.initUI()
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> initUI(self):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将窗口设置为动图大小</span>
self.resize(1000, 800<span style="color: rgba(0, 0, 0, 1)">)
self.browser </span>=<span style="color: rgba(0, 0, 0, 1)"> QWebEngineView()
self.browser.load(QUrl(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">https://www.jd.com</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">))
self.setCentralWidget(self.browser)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 添加窗口标题</span>
self.setWindowTitle(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">WebEngineDemo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
app </span>=<span style="color: rgba(0, 0, 0, 1)"> QApplication(sys.argv)
app.setWindowIcon(QIcon(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">images/icon.ico</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">))
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个主窗口</span>
mainWin =<span style="color: rgba(0, 0, 0, 1)"> DemoWin()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 显示</span>
<span style="color: rgba(0, 0, 0, 1)"> mainWin.show()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 主循环</span>
sys.exit(app.exec_())</pre>
</div>
<p>实现效果:</p>
<p><img src="https://img2020.cnblogs.com/blog/1244144/202006/1244144-20200616162740751-1843362136.gif" alt="" loading="lazy"></p>
<h2>二、加载本地web页面</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> sys
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> os
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 使用调色板等</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtCore <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Qt, QUrl
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtGui <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QIcon
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 导入QT,其中包含一些常量,例如颜色等</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 导入常用组件</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QApplication, QMainWindow, QTextEdit
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QMdiArea, QMdiSubWindow
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWebEngineWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QWebEnginePage, QWebEngineView
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> DemoWin(QMainWindow):
count </span>=<span style="color: rgba(0, 0, 0, 1)"> 0
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self):
super(DemoWin, self).</span><span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">()
self.initUI()
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> initUI(self):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将窗口设置为动图大小</span>
self.resize(500, 500<span style="color: rgba(0, 0, 0, 1)">)
self.browser </span>=<span style="color: rgba(0, 0, 0, 1)"> QWebEngineView()
url </span>= os.getcwd() + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/test.html</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
self.browser.load(QUrl.fromLocalFile(url))
self.setCentralWidget(self.browser)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 添加窗口标题</span>
self.setWindowTitle(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">WebEngineDemo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
app </span>=<span style="color: rgba(0, 0, 0, 1)"> QApplication(sys.argv)
app.setWindowIcon(QIcon(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">images/icon.ico</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">))
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个主窗口</span>
mainWin =<span style="color: rgba(0, 0, 0, 1)"> DemoWin()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 显示</span>
<span style="color: rgba(0, 0, 0, 1)"> mainWin.show()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 主循环</span>
sys.exit(app.exec_())</pre>
</div>
<p>效果:</p>
<p><img src="https://img2020.cnblogs.com/blog/1244144/202006/1244144-20200616163057009-937288036.png" alt="" loading="lazy"></p>
<h2>三、嵌入HTML</h2>
<p>前面我们都是使用的QWebEngineView控件来打开Web页面或加载本地Html页面,除了这种方式,我们也可以直接将Html代码嵌入到窗口中。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> sys
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> os
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 使用调色板等</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtCore <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Qt, QUrl
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtGui <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QIcon
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 导入QT,其中包含一些常量,例如颜色等</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 导入常用组件</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QApplication, QMainWindow, QTextEdit
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QMdiArea, QMdiSubWindow
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWebEngineWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QWebEnginePage, QWebEngineView
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> DemoWin(QMainWindow):
count </span>=<span style="color: rgba(0, 0, 0, 1)"> 0
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self):
super(DemoWin, self).</span><span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">()
self.initUI()
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> initUI(self):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将窗口设置为动图大小</span>
self.resize(500, 500<span style="color: rgba(0, 0, 0, 1)">)
self.browser </span>=<span style="color: rgba(0, 0, 0, 1)"> QWebEngineView()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 直接将html代码嵌入控件</span>
self.browser.setHtml(<span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>TEST Page</title>
</head>
<body>
<h1>TEST</h1>
<h2>TEST</h2>
<h3>TEST</h3>
<h4>TEST</h4>
<h5>TEST</h5>
<h6>TEST</h6>
</body>
</html>
</span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(0, 0, 0, 1)">)
self.setCentralWidget(self.browser)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 添加窗口标题</span>
self.setWindowTitle(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">WebEngineDemo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
app </span>=<span style="color: rgba(0, 0, 0, 1)"> QApplication(sys.argv)
app.setWindowIcon(QIcon(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">images/icon.ico</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">))
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个主窗口</span>
mainWin =<span style="color: rgba(0, 0, 0, 1)"> DemoWin()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 显示</span>
<span style="color: rgba(0, 0, 0, 1)"> mainWin.show()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 主循环</span>
sys.exit(app.exec_())</pre>
</div>
<p>效果:</p>
<p><img src="https://img2020.cnblogs.com/blog/1244144/202006/1244144-20200616163057009-937288036.png" alt="" loading="lazy"></p>
<h2>四、PyQt5调用html页面中的JS代码</h2>
<p>编写一个Html页面,其中包含JS代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><!</span><span style="color: rgba(255, 0, 255, 1)">DOCTYPE html</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">html </span><span style="color: rgba(255, 0, 0, 1)">lang</span><span style="color: rgba(0, 0, 255, 1)">="en"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">meta </span><span style="color: rgba(255, 0, 0, 1)">charset</span><span style="color: rgba(0, 0, 255, 1)">="UTF-8"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">></span>TEST Page<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">script</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">function</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> fullName(value) {
alert(value);
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">var</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> firstname </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">=</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> document.getElementById(</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">firstname</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">).value;
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">var</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> lastname </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">=</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> document.getElementById(</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">lastname</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">).value;
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">var</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> fullname </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">=</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> firstname </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">+</span> <span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">"</span> <span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">"</span> <span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">+</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> lastname;
document.getElementById(</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">fullname</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">).value </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">=</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> fullname;
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">return</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> fullname;
}
</span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">script</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">form</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">></span>First Name:<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">input </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="firstname"</span><span style="color: rgba(255, 0, 0, 1)"> id</span><span style="color: rgba(0, 0, 255, 1)">="firstname"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">br</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">></span>Last Name:<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">input </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="lastname"</span><span style="color: rgba(255, 0, 0, 1)"> id</span><span style="color: rgba(0, 0, 255, 1)">="lastname"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">br</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">></span>Full Name:<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">input </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="fullname"</span><span style="color: rgba(255, 0, 0, 1)"> id</span><span style="color: rgba(0, 0, 255, 1)">="fullname"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">form</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p>编写PyQt5代码调用页面中的JS代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> sys
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> os
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 使用调色板等</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtCore <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Qt, QUrl
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtGui <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QIcon
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 导入QT,其中包含一些常量,例如颜色等</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 导入常用组件</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QApplication, QWidget, QVBoxLayout
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QPushButton
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWebEngineWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QWebEngineView
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> DemoWin(QWidget):
count </span>=<span style="color: rgba(0, 0, 0, 1)"> 0
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self):
super(DemoWin, self).</span><span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">()
self.initUI()
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> initUI(self):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将窗口设置为动图大小</span>
self.resize(500, 200<span style="color: rgba(0, 0, 0, 1)">)
self.browser </span>=<span style="color: rgba(0, 0, 0, 1)"> QWebEngineView()
url </span>= os.getcwd() + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/test.html</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 加载test.html</span>
<span style="color: rgba(0, 0, 0, 1)"> self.browser.load(QUrl.fromLocalFile(url))
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 定义一个按钮,在槽函数中调用JS函数</span>
self.addBtn = QPushButton(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">获取全名</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
self.addBtn.clicked.connect(self.getFullName)
layout </span>=<span style="color: rgba(0, 0, 0, 1)"> QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.addBtn)
self.setLayout(layout)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 添加窗口标题</span>
self.setWindowTitle(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">JSDemo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> getFullName(self):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 传递参数value到JS函数</span>
value = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello World</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 调用JS中的fullName函数</span>
self.browser.page().runJavaScript(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">fullName("</span><span style="color: rgba(128, 0, 0, 1)">'</span> + value + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">");</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
app </span>=<span style="color: rgba(0, 0, 0, 1)"> QApplication(sys.argv)
app.setWindowIcon(QIcon(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">images/icon.ico</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">))
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个主窗口</span>
mainWin =<span style="color: rgba(0, 0, 0, 1)"> DemoWin()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 显示</span>
<span style="color: rgba(0, 0, 0, 1)"> mainWin.show()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 主循环</span>
sys.exit(app.exec_())</pre>
</div>
<p>实现效果:</p>
<p><img src="https://img2020.cnblogs.com/blog/1244144/202006/1244144-20200617104937245-685878142.gif" alt="" loading="lazy"></p>
<h2>五、Html页面中的JS代码调用Python代码</h2>
<p>在HTML的JS代码中调用PyQt5的代码比较繁琐,如下代码所示。</p>
<p>HTML代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><!</span><span style="color: rgba(255, 0, 255, 1)">DOCTYPE html</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">html </span><span style="color: rgba(255, 0, 0, 1)">lang</span><span style="color: rgba(0, 0, 255, 1)">="en"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">meta </span><span style="color: rgba(255, 0, 0, 1)">charset</span><span style="color: rgba(0, 0, 255, 1)">="UTF-8"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">></span>TEST Page<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="background-color: rgba(255, 255, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">script </span><span style="color: rgba(255, 0, 0, 1)">src</span><span style="color: rgba(0, 0, 255, 1)">="./qwebchannel.js"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">script</span><span style="color: rgba(0, 0, 255, 1)">></span></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">script </span><span style="color: rgba(255, 0, 0, 1)">language</span><span style="color: rgba(0, 0, 255, 1)">="javascript"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)">//</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)"> 用于PyQt5代码返回值后调用</span>
<span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">function</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> callback(result) {
alert(</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">计算结果:</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span> <span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">+</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> result);
}
document.addEventListener(</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">"</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">DOMContentLoaded</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">"</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">, </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">function</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> () {
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)">//</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)"> 这里面的channel就是PyQt5传递过来的channel对象,其中包含了可供调用的obj对象(一个Factorial类对象)</span>
<span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">new</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> QWebChannel(qt.webChannelTransport, </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">function</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> (channel) {
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)">//</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)"> 从channel中获取到我们注册到channel中的Factorial类对象</span>
<span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> window.obj </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">=</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> channel.objects.obj;
});
});
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">function</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> onFactorial() {
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)">//</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)"> 如果获取到了Factorial对象</span>
<span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">if</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> (window.obj) {
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)">//</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)"> 获取输入框中的数字</span>
<span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 255, 1)">var</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> n </span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">=</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> parseInt(document.getElementById(</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">n</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">'</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)">).value);
</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)">//</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)"> 调用Factorial类对象中的槽函数factorial(n),并且指定一个异步调用的callback函数,当factorial返回时</span>
<span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)">//</span><span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 128, 0, 1)"> 自动调用callback</span>
<span style="background-color: rgba(245, 245, 245, 1); color: rgba(0, 0, 0, 1)"> window.obj.factorial(n, callback);
}
}
</span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">script</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">form</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">></span>请输入N:<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">input </span><span style="color: rgba(255, 0, 0, 1)">type</span><span style="color: rgba(0, 0, 255, 1)">="text"</span><span style="color: rgba(255, 0, 0, 1)"> id</span><span style="color: rgba(0, 0, 255, 1)">="n"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">br</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">input </span><span style="color: rgba(255, 0, 0, 1)">type</span><span style="color: rgba(0, 0, 255, 1)">="button"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="计算阶乘"</span><span style="color: rgba(255, 0, 0, 1)"> onclick</span><span style="color: rgba(0, 0, 255, 1)">="onFactorial()"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">form</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p>注意,这里需要导入一个PyQt5提供的js文件:qwebchannel.js,内容如下:</p>
<div class="cnblogs_code"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" id="code_img_closed_1c0c1bc1-20a0-45cf-b7c2-64a9e002c52a" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" id="code_img_opened_1c0c1bc1-20a0-45cf-b7c2-64a9e002c52a" class="code_img_opened" style="display: none">
<div id="cnblogs_code_open_1c0c1bc1-20a0-45cf-b7c2-64a9e002c52a" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">***************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebChannel module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
***************************************************************************</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
"use strict"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> QWebChannelMessageTypes =<span style="color: rgba(0, 0, 0, 1)"> {
signal: </span>1<span style="color: rgba(0, 0, 0, 1)">,
propertyUpdate: </span>2<span style="color: rgba(0, 0, 0, 1)">,
init: </span>3<span style="color: rgba(0, 0, 0, 1)">,
idle: </span>4<span style="color: rgba(0, 0, 0, 1)">,
debug: </span>5<span style="color: rgba(0, 0, 0, 1)">,
invokeMethod: </span>6<span style="color: rgba(0, 0, 0, 1)">,
connectToSignal: </span>7<span style="color: rgba(0, 0, 0, 1)">,
disconnectFromSignal: </span>8<span style="color: rgba(0, 0, 0, 1)">,
setProperty: </span>9<span style="color: rgba(0, 0, 0, 1)">,
response: </span>10<span style="color: rgba(0, 0, 0, 1)">,
};
</span><span style="color: rgba(0, 0, 255, 1)">var</span> QWebChannel = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(transport, initCallback)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> transport !== "object" || <span style="color: rgba(0, 0, 255, 1)">typeof</span> transport.send !== "function"<span style="color: rgba(0, 0, 0, 1)">) {
console.error(</span>"The QWebChannel expects a transport object with a send function and onmessage callback property." +
" Given is: transport: " + <span style="color: rgba(0, 0, 255, 1)">typeof</span>(transport) + ", transport.send: " + <span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(transport.send));
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> channel = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.transport =<span style="color: rgba(0, 0, 0, 1)"> transport;
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.send = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(data)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span>(data) !== "string"<span style="color: rgba(0, 0, 0, 1)">) {
data </span>=<span style="color: rgba(0, 0, 0, 1)"> JSON.stringify(data);
}
channel.transport.send(data);
}
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.transport.onmessage = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(message)
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> data =<span style="color: rgba(0, 0, 0, 1)"> message.data;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> data === "string"<span style="color: rgba(0, 0, 0, 1)">) {
data </span>=<span style="color: rgba(0, 0, 0, 1)"> JSON.parse(data);
}
</span><span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)"> (data.type) {
</span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> QWebChannelMessageTypes.signal:
channel.handleSignal(data);
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> QWebChannelMessageTypes.response:
channel.handleResponse(data);
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> QWebChannelMessageTypes.propertyUpdate:
channel.handlePropertyUpdate(data);
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)">:
console.error(</span>"invalid message received:"<span style="color: rgba(0, 0, 0, 1)">, message.data);
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.execCallbacks =<span style="color: rgba(0, 0, 0, 1)"> {};
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.execId = 0<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.exec = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(data, callback)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">callback) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> if no callback is given, send directly</span>
<span style="color: rgba(0, 0, 0, 1)"> channel.send(data);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (channel.execId ===<span style="color: rgba(0, 0, 0, 1)"> Number.MAX_VALUE) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> wrap</span>
channel.execId =<span style="color: rgba(0, 0, 0, 1)"> Number.MIN_VALUE;
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (data.hasOwnProperty("id"<span style="color: rgba(0, 0, 0, 1)">)) {
console.error(</span>"Cannot exec message with property id: " +<span style="color: rgba(0, 0, 0, 1)"> JSON.stringify(data));
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
data.id </span>= channel.execId++<span style="color: rgba(0, 0, 0, 1)">;
channel.execCallbacks </span>=<span style="color: rgba(0, 0, 0, 1)"> callback;
channel.send(data);
};
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.objects =<span style="color: rgba(0, 0, 0, 1)"> {};
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.handleSignal = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(message)
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> object =<span style="color: rgba(0, 0, 0, 1)"> channel.objects;
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (object) {
object.signalEmitted(message.signal, message.args);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
console.warn(</span>"Unhandled signal: " + message.object + "::" +<span style="color: rgba(0, 0, 0, 1)"> message.signal);
}
}
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.handleResponse = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(message)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!message.hasOwnProperty("id"<span style="color: rgba(0, 0, 0, 1)">)) {
console.error(</span>"Invalid response message received: "<span style="color: rgba(0, 0, 0, 1)">, JSON.stringify(message));
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
channel.execCallbacks(message.data);
</span><span style="color: rgba(0, 0, 255, 1)">delete</span><span style="color: rgba(0, 0, 0, 1)"> channel.execCallbacks;
}
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.handlePropertyUpdate = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(message)
{
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> message.data) {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> data =<span style="color: rgba(0, 0, 0, 1)"> message.data;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> object =<span style="color: rgba(0, 0, 0, 1)"> channel.objects;
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (object) {
object.propertyUpdate(data.signals, data.properties);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
console.warn(</span>"Unhandled property update: " + data.object + "::" +<span style="color: rgba(0, 0, 0, 1)"> data.signal);
}
}
channel.exec({type: QWebChannelMessageTypes.idle});
}
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.debug = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(message)
{
channel.send({type: QWebChannelMessageTypes.debug, data: message});
};
channel.exec({type: QWebChannelMessageTypes.init}, </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(data) {
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> objectName <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> data) {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> object = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> QObject(objectName, data, channel);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> now unwrap properties, which might reference other registered objects</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> objectName <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> channel.objects) {
channel.objects.unwrapProperties();
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (initCallback) {
initCallback(channel);
}
channel.exec({type: QWebChannelMessageTypes.idle});
});
};
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> QObject(name, data, webChannel)
{
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.__id__ =<span style="color: rgba(0, 0, 0, 1)"> name;
webChannel.objects </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> List of callbacks that get invoked upon signal emission</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.__objectSignals__ =<span style="color: rgba(0, 0, 0, 1)"> {};
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Cache of all properties, updated when a notify signal is emitted</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.__propertyCache__ =<span style="color: rgba(0, 0, 0, 1)"> {};
</span><span style="color: rgba(0, 0, 255, 1)">var</span> object = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ----------------------------------------------------------------------</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.unwrapQObject = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(response)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (response <span style="color: rgba(0, 0, 255, 1)">instanceof</span><span style="color: rgba(0, 0, 0, 1)"> Array) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> support list of objects</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> ret = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Array(response.length);
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i = 0; i < response.length; ++<span style="color: rgba(0, 0, 0, 1)">i) {
ret </span>=<span style="color: rgba(0, 0, 0, 1)"> object.unwrapQObject(response);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ret;
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">response
</span>|| !response["__QObject*__"<span style="color: rgba(0, 0, 0, 1)">]
</span>|| response.id ===<span style="color: rgba(0, 0, 0, 1)"> undefined) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> response;
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> objectId =<span style="color: rgba(0, 0, 0, 1)"> response.id;
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (webChannel.objects)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> webChannel.objects;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">response.data) {
console.error(</span>"Cannot unwrap unknown QObject " + objectId + " without data."<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> qObject = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> QObject( objectId, response.data, webChannel );
qObject.destroyed.connect(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (webChannel.objects ===<span style="color: rgba(0, 0, 0, 1)"> qObject) {
</span><span style="color: rgba(0, 0, 255, 1)">delete</span><span style="color: rgba(0, 0, 0, 1)"> webChannel.objects;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> reset the now deleted QObject to an empty {} object</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> just assigning {} though would not have the desired effect, but the</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> below also ensures all external references will see the empty map</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> NOTE: this detour is necessary to workaround QTBUG-40021</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> propertyNames =<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> propertyName <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> qObject) {
propertyNames.push(propertyName);
}
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> idx <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> propertyNames) {
</span><span style="color: rgba(0, 0, 255, 1)">delete</span><span style="color: rgba(0, 0, 0, 1)"> qObject];
}
}
});
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> here we are already initialized, and thus must directly unwrap the properties</span>
<span style="color: rgba(0, 0, 0, 1)"> qObject.unwrapProperties();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> qObject;
}
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.unwrapProperties = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">()
{
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> propertyIdx <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> object.__propertyCache__) {
object.__propertyCache__ </span>=<span style="color: rgba(0, 0, 0, 1)"> object.unwrapQObject(object.__propertyCache__);
}
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> addSignal(signalData, isPropertyNotifySignal)
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> signalName = signalData;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> signalIndex = signalData;
object </span>=<span style="color: rgba(0, 0, 0, 1)"> {
connect: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(callback) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span>(callback) !== "function"<span style="color: rgba(0, 0, 0, 1)">) {
console.error(</span>"Bad callback given to connect to signal " +<span style="color: rgba(0, 0, 0, 1)"> signalName);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
object.__objectSignals__ </span>= object.__objectSignals__ ||<span style="color: rgba(0, 0, 0, 1)"> [];
object.__objectSignals__.push(callback);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!isPropertyNotifySignal && signalName !== "destroyed"<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> only required for "pure" signals, handled separately for properties in propertyUpdate</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> also note that we always get notified about the destroyed signal</span>
<span style="color: rgba(0, 0, 0, 1)"> webChannel.exec({
type: QWebChannelMessageTypes.connectToSignal,
object: object.__id__,
signal: signalIndex
});
}
},
disconnect: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(callback) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span>(callback) !== "function"<span style="color: rgba(0, 0, 0, 1)">) {
console.error(</span>"Bad callback given to disconnect from signal " +<span style="color: rgba(0, 0, 0, 1)"> signalName);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
object.__objectSignals__ </span>= object.__objectSignals__ ||<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(0, 0, 255, 1)">var</span> idx =<span style="color: rgba(0, 0, 0, 1)"> object.__objectSignals__.indexOf(callback);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (idx === -1<span style="color: rgba(0, 0, 0, 1)">) {
console.error(</span>"Cannot find connection of signal " + signalName + " to " +<span style="color: rgba(0, 0, 0, 1)"> callback.name);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
object.__objectSignals__.splice(idx, </span>1<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!isPropertyNotifySignal && object.__objectSignals__.length === 0<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> only required for "pure" signals, handled separately for properties in propertyUpdate</span>
<span style="color: rgba(0, 0, 0, 1)"> webChannel.exec({
type: QWebChannelMessageTypes.disconnectFromSignal,
object: object.__id__,
signal: signalIndex
});
}
}
};
}
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* Invokes all callbacks for the given signalname. Also works for property notify callbacks.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> invokeSignalCallbacks(signalName, signalArgs)
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> connections =<span style="color: rgba(0, 0, 0, 1)"> object.__objectSignals__;
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (connections) {
connections.forEach(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(callback) {
callback.apply(callback, signalArgs);
});
}
}
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.propertyUpdate = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(signals, propertyMap)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> update property cache</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> propertyIndex <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> propertyMap) {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> propertyValue =<span style="color: rgba(0, 0, 0, 1)"> propertyMap;
object.__propertyCache__ </span>=<span style="color: rgba(0, 0, 0, 1)"> propertyValue;
}
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> signalName <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> signals) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Invoke all callbacks, as signalEmitted() does not. This ensures the</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> property cache is updated before the callbacks are invoked.</span>
<span style="color: rgba(0, 0, 0, 1)"> invokeSignalCallbacks(signalName, signals);
}
}
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.signalEmitted = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(signalName, signalArgs)
{
invokeSignalCallbacks(signalName, signalArgs);
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> addMethod(methodData)
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> methodName = methodData;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> methodIdx = methodData;
object </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> args =<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)"> callback;
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i = 0; i < arguments.length; ++<span style="color: rgba(0, 0, 0, 1)">i) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> arguments === "function"<span style="color: rgba(0, 0, 0, 1)">)
callback </span>=<span style="color: rgba(0, 0, 0, 1)"> arguments;
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
args.push(arguments);
}
webChannel.exec({
</span>"type"<span style="color: rgba(0, 0, 0, 1)">: QWebChannelMessageTypes.invokeMethod,
</span>"object"<span style="color: rgba(0, 0, 0, 1)">: object.__id__,
</span>"method"<span style="color: rgba(0, 0, 0, 1)">: methodIdx,
</span>"args"<span style="color: rgba(0, 0, 0, 1)">: args
}, </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(response) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (response !==<span style="color: rgba(0, 0, 0, 1)"> undefined) {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> result =<span style="color: rgba(0, 0, 0, 1)"> object.unwrapQObject(response);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (callback) {
(callback)(result);
}
}
});
};
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> bindGetterSetter(propertyInfo)
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> propertyIndex = propertyInfo;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> propertyName = propertyInfo;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> notifySignalData = propertyInfo;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> initialize property cache with current value</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> NOTE: if this is an object, it is not directly unwrapped as it might</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> reference other QObject that we do not know yet</span>
object.__propertyCache__ = propertyInfo;
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (notifySignalData) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (notifySignalData === 1<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> signal name is optimized away, reconstruct the actual name</span>
notifySignalData = propertyName + "Changed"<span style="color: rgba(0, 0, 0, 1)">;
}
addSignal(notifySignalData, </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
}
Object.defineProperty(object, propertyName, {
configurable: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
get: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> propertyValue =<span style="color: rgba(0, 0, 0, 1)"> object.__propertyCache__;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (propertyValue ===<span style="color: rgba(0, 0, 0, 1)"> undefined) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> This shouldn't happen</span>
console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " +<span style="color: rgba(0, 0, 0, 1)"> object.__id__);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> propertyValue;
},
set: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(value) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (value ===<span style="color: rgba(0, 0, 0, 1)"> undefined) {
console.warn(</span>"Property setter for " + propertyName + " called with undefined value!"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
object.__propertyCache__ </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
webChannel.exec({
</span>"type"<span style="color: rgba(0, 0, 0, 1)">: QWebChannelMessageTypes.setProperty,
</span>"object"<span style="color: rgba(0, 0, 0, 1)">: object.__id__,
</span>"property"<span style="color: rgba(0, 0, 0, 1)">: propertyIndex,
</span>"value"<span style="color: rgba(0, 0, 0, 1)">: value
});
}
});
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ----------------------------------------------------------------------</span>
<span style="color: rgba(0, 0, 0, 1)">
data.methods.forEach(addMethod);
data.properties.forEach(bindGetterSetter);
data.signals.forEach(</span><span style="color: rgba(0, 0, 255, 1)">function</span>(signal) { addSignal(signal, <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">); });
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> name <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> data.enums) {
object </span>=<span style="color: rgba(0, 0, 0, 1)"> data.enums;
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">required for use with nodejs</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> module === 'object'<span style="color: rgba(0, 0, 0, 1)">) {
module.exports </span>=<span style="color: rgba(0, 0, 0, 1)"> {
QWebChannel: QWebChannel
};
}</span></pre>
</div>
<span class="cnblogs_code_collapse">qwebchannel.js</span></div>
<p>PyQt5代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> sys
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> os
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 使用调色板等</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtCore <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> Qt, QUrl, QObject, pyqtSlot
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtGui <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QIcon
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 导入QT,其中包含一些常量,例如颜色等</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 导入常用组件</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QApplication, QWidget, QVBoxLayout
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QPushButton
</span><span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWebEngineWidgets <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QWebEngineView
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 导入QWebChannel</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> PyQt5.QtWebChannel <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> QWebChannel
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 定义一个类,其中包含一个槽函数,供JS代码调用来计算阶乘</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Factorial(QObject):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将其定义为一个槽函数,参数类型为int,返回值类型为int</span>
@pyqtSlot(int, result=<span style="color: rgba(0, 0, 0, 1)">int)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> factorial(self, n):
</span><span style="color: rgba(0, 0, 255, 1)">if</span> n == 0 <span style="color: rgba(0, 0, 255, 1)">or</span> n == 1<span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 0, 255, 1)">return</span> 1
<span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 0, 255, 1)">return</span> self.factorial(n - 1) *<span style="color: rgba(0, 0, 0, 1)"> n
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 定义一个channel全局对象,用于注册一些对象提供给html页面中的JS代码调用</span>
channel =<span style="color: rgba(0, 0, 0, 1)"> QWebChannel()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 定义一个对象,其中包含槽函数,注册到channel可以传递给JS代码</span>
factorial =<span style="color: rgba(0, 0, 0, 1)"> Factorial()
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> DemoWin(QWidget):
count </span>=<span style="color: rgba(0, 0, 0, 1)"> 0
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self):
super(DemoWin, self).</span><span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">()
self.initUI()
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> initUI(self):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将窗口设置为动图大小</span>
self.resize(500, 200<span style="color: rgba(0, 0, 0, 1)">)
self.browser </span>=<span style="color: rgba(0, 0, 0, 1)"> QWebEngineView()
url </span>= os.getcwd() + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/test.html</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 加载test.html</span>
<span style="color: rgba(0, 0, 0, 1)"> self.browser.load(QUrl.fromLocalFile(url))
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将factorial对象注册到channel中,名字为obj,JS中使用这个名字来调用函数</span>
channel.registerObject(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">obj</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, factorial)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将channel传递给html中的JS</span>
<span style="color: rgba(0, 0, 0, 1)"> self.browser.page().setWebChannel(channel)
layout </span>=<span style="color: rgba(0, 0, 0, 1)"> QVBoxLayout()
layout.addWidget(self.browser)
self.setLayout(layout)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 添加窗口标题</span>
self.setWindowTitle(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">JSDemo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> getFullName(self):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 传递参数value到JS函数</span>
value = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello World</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 调用JS中的fullName函数</span>
self.browser.page().runJavaScript(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">fullName("</span><span style="color: rgba(128, 0, 0, 1)">'</span> + value + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">");</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
app </span>=<span style="color: rgba(0, 0, 0, 1)"> QApplication(sys.argv)
app.setWindowIcon(QIcon(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">images/icon.ico</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">))
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建一个主窗口</span>
mainWin =<span style="color: rgba(0, 0, 0, 1)"> DemoWin()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 显示</span>
<span style="color: rgba(0, 0, 0, 1)"> mainWin.show()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 主循环</span>
sys.exit(app.exec_())</pre>
</div>
<p>实现效果:</p>
<p><img src="https://img2020.cnblogs.com/blog/1244144/202006/1244144-20200617113349364-705609263.gif" alt="" loading="lazy"></p>
<p> </p>
<p>===</p>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
保持学习,否则迟早要被淘汰*(^ 。 ^ )***<br><br>
来源:https://www.cnblogs.com/leokale-zz/p/13141751.html
頁:
[1]