清晰运转 發表於 2020-6-17 10:50:00

[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)">
      &lt;!DOCTYPE html&gt;
      &lt;html lang="en"&gt;
      &lt;head&gt;
            &lt;meta charset="UTF-8"&gt;
            &lt;title&gt;TEST Page&lt;/title&gt;
      &lt;/head&gt;
      &lt;body&gt;
      &lt;h1&gt;TEST&lt;/h1&gt;
      &lt;h2&gt;TEST&lt;/h2&gt;
      &lt;h3&gt;TEST&lt;/h3&gt;
      &lt;h4&gt;TEST&lt;/h4&gt;
      &lt;h5&gt;TEST&lt;/h5&gt;
      &lt;h6&gt;TEST&lt;/h6&gt;
      &lt;/body&gt;
      &lt;/html&gt;
      </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)">&lt;!</span><span style="color: rgba(255, 0, 255, 1)">DOCTYPE html</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>TEST Page<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">script</span><span style="color: rgba(0, 0, 255, 1)">&gt;</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)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">script</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">form</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>First Name:<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">br</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>Last Name:<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">br</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>Full Name:<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">form</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">&gt;</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)">&lt;!</span><span style="color: rgba(255, 0, 255, 1)">DOCTYPE html</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>TEST Page<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="background-color: rgba(255, 255, 0, 1)"><span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">script</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</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)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">script</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">form</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>请输入N:<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">label</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">br</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</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)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">form</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">&gt;</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 &lt;milian.wolff@kdab.com&gt;
** 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 &lt; 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 &amp;&amp; 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 &amp;&amp; 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 &lt; 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>&nbsp;</p>
<p>===</p>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    保持学习,否则迟早要被淘汰*(^ 。 ^ )***<br><br>
来源:https://www.cnblogs.com/leokale-zz/p/13141751.html
頁: [1]
查看完整版本: [Python自学] PyQT5-Web控件、与JavaScript交互