• PyQt5快速开发与实战 5.4 网页交互


    PyQt5快速开发与实战

    5. 第5章 PyQt5 高级界面控件

    5.4 网页交互

    PyQt 5使用QWebEngineView控件来展示HTML 页面,对老版本中的QWebView类不再进行维护,因为 QWebEngineView使用 Chromium内核可以给用户带来更好的体验。

    Qt慢慢淘汰了古老的 WebKit,取而代之的是使用WebEngine框架。WebEngine是基于谷歌的 Chromium引擎开发的,也就是内部集成了谷歌的Chromium引擎。WebEngine框架是基于Chromium上的 Content API封装,投入成本比较小,可以很好地支持HTML 5。

    在PyQt5中可以通过 PyQt5.QtWebKitWidgets.QWebEngineView类来使用网页控件

    Qobject → QLayout → QWidget → QWenEngineView

    5.4.1 QWebEngineView类中的常用方法
    方法描述
    load(QUrl url)加载指定的URL并显示
    setHtml(QString &html)将网页视图的内容设置为指定的HTML内容

    OWebEngineView控件使用load()函数加载一个 Web页面,实际上就是使用HTTP GET方法加载 Web页面。这个控件既可以加载本地的Web页面也可以加载远程的外部 Web页面。

    先要自行安装

    pip install PyQtWebEngine -i https://pypi.tuna.tsinghua.edu.cn/simple
    
    • 1

    在这里插入图片描述

    from PyQt5.QtCore import QUrl
    from PyQt5.QtWebEngineWidgets import *
    
    
    view = QWebEngineView()
    view.load(QUrl("https://blog.csdn.net/weixin_44226181?type=blog"))
    view.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    5.4.2 案例——加载并显示外部的Web页面
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtWebEngineWidgets import *
    import sys
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.setWindowTitle("打开外部网页案例")
            self.setGeometry(5,30,1355,730)
            self.browser = QWebEngineView()
    
            self.browser.load(QUrl("https://blog.csdn.net/weixin_44226181?type=blog"))
            self.setCentralWidget(self.browser)
    
    if __name__ == '__main__':
        from pyqt5_plugins.examples.exampleqmlitem import QtCore
        QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
        app = QApplication(sys.argv)
        win = MainWindow()
        win.show()
        sys.exit(app.exec_())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    5.4.3 案例——加载并显示本地的Web页面
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtWebEngineWidgets import *
    import sys
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.setWindowTitle("打开本地页面案例")
            self.setGeometry(5,30,555,330)
            self.browser = QWebEngineView()
    
            url = r'D:/DingJiaxiong/PycharmProjects/PyQt5Study/网页交互/index.html'
            self.browser.load(QUrl(url))
            self.setCentralWidget(self.browser)
    
    if __name__ == '__main__':
        from pyqt5_plugins.examples.exampleqmlitem import QtCore
        QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
        app = QApplication(sys.argv)
        win = MainWindow()
        win.show()
        sys.exit(app.exec_())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    5.4.4 案例——加载并显示嵌入的HTML代码
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtWebEngineWidgets import *
    import sys
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.setWindowTitle("打开本地页面HTML代码案例")
            self.setGeometry(5, 30, 555, 330)
            self.browser = QWebEngineView()
    
            self.browser.setHtml("""
            
    
    
        
        丁家雄!
    
    
    

    Hello,DingJiaxiong!

    """
    ) self.setCentralWidget(self.browser) if __name__ == '__main__': from pyqt5_plugins.examples.exampleqmlitem import QtCore QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) app = QApplication(sys.argv) win = MainWindow() win.show() sys.exit(app.exec_())
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在这里插入图片描述

    经过测试,使用 QWebEngine View对象的setHtml())函数渲染HTML页面时,如果页面中使用的JavaScript代码超过2MB,程序渲染的页面就会渲染失败,页面中会出现大片的空白。

    5.4.5 案例——PyQt调用JavaScript代码

    通过 QWebEnginePage类的 runJavaScript(str, Callable)函数可以很方便地实现PyQt和 HTML/JavaScript的双向通信,也实现了Python 代码和 HTML/JavaScript 代码的解耦,便于开发人员进行分工协作。

    from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
    from PyQt5.QtWebEngineWidgets import QWebEngineView
    import sys
    from pyqt5_plugins.examples.exampleqmlitem import QtCore
    QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
    # 创建一个 application实例
    app = QApplication(sys.argv)
    win = QWidget()
    win.setWindowTitle('Web页面中的JavaScript与 QWebEngineView交互例子')
    
    # 创建一个垂直布局器
    layout = QVBoxLayout()
    win.setLayout(layout)
    
    # 创建一个 QWebEngineView 对象
    view = QWebEngineView()
    view.setHtml('''
      
        
          A Demo Page
    
          
        
    
        
          



    '''
    ) # 创建一个按钮去调用 JavaScript代码 button = QPushButton('设置全名') def js_callback(result): print(result) def complete_name(): view.page().runJavaScript('completeAndReturnName();', js_callback) # 按钮连接 'complete_name'槽,当点击按钮是会触发信号 button.clicked.connect(complete_name) # 把QWebView和button加载到layout布局中 layout.addWidget(view) layout.addWidget(button) # 显示窗口和运行app win.show() sys.exit(app.exec_())
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    在这里插入图片描述

    5.4.6 案例——JavaScript调用PyQt代码

    JavaScript调用PyOt代码,是指PyOt可以与加载的 Web页面进行双向的数据交互。首先,使用QWebEngineView对象加载Web页面后,就可以获得页面中表单输入数据,在Web页面中通过JavaScript 代码收集用户提交的数据。然后,在 Web页面中,JavaScript通过桥连接方式传递数据给PyQt。最后,PyQt 接收到页面传递的数据,经过业务处理后,还可以把处理过的数据返给Web页面。

    1. 创建QWebChannel对象

      创建QWebChannel对象,注册一个需要桥接的对象,以便Web页面的JavaScript使用。

      channel = QWebChannel()
      myobj = MySharedObject()
      channel.registerObject("bridge",myobj)
      view.page().setWebChannel(channel)
      
      • 1
      • 2
      • 3
      • 4
    2. 创建共享数据的PyQt对象

      class MySharcedObject(QWidget):
          def __init__(self):
              super(MySharcedObject, self).__init__()
          
          def _setStrValue(self,str):
              print("获得页面参数: %s" % str)
          
          # 定义对外发布的方法
          strValue = pyqtProperty(str,fset = _setStrValue)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      对外提供的 PyOt对象方法,需要使用pyqtProperty()函数让它暴露出来。

      在PyQt5中使用pyqtProperty()函数来定义PyQt对象中的属性,这个函数的使用方式与标准Python模块中的property()函数相同。PyQt5.QtCore.pyqtProperty()函数的API如下:

      PyQt5.Qtcore.pyqtProperty(type[, fget=None[,fset=None[, freset=None [,fdel=None[, doc=None[, designable=True[, scriptable=True[, stored=True[,user=False[,constant=False[, final=False[,notify=None [,
      revision=0]]]]]]]]])
      
      • 1
      • 2

      参数说明

      参数说明
      type必填,属性的类型
      fget可选,用于获取属性的值
      fset可选,用于设置属性的值
      freset可选,用于将属性的值重置为它的默认值
      fdel可选,用于删除属性
      Doc可选,属性的文档字符串
      designable可选,设置Qt DESIGNABLE标志
      scriptable可选,设置Qt SCRIPTABLE标志
      stored可选,设置Qt STORED标志
      user可选,设置Qt USER标志
      constant可选,设置Qt CONSTANT标志
      final可选,设置Qt FINAL标志
      notify可选,未绑定的通知信号
      revision可选,将版本导出到QML

      测试案例

      from PyQt5.QtCore import QObject, pyqtProperty
      
      
      class MyObject(QObject):
          def __init__(self, inVal=20):
              self.val = inVal
      
          def readVal(self):
              print('readVal=%s' % self.val)
              return self.val
      
          def setVal(self, val):
              print('setVal=%s' % val)
              self.val = val
      
          ppVal = pyqtProperty(int, readVal, setVal)
      
      
      if __name__ == '__main__':
          obj = MyObject()
          print('\n#1')
          obj.ppVal = 10
          print('\n#2')
          print('obj.ppVal=%s' % obj.ppVal)
          print('obj.readVal()=%s' % obj.readVal())
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25

      在这里插入图片描述

    3. 创建调用PyQt的Web页面

      本机直接启动服务

      DOCTYPE html>
      <html lang="en">
      <head>
          <title>A Demo Pagetitle>
          <meta charset="UTF-8">
          <script src="qwebchannel.js">script>
          <script>
              function completeAndReturnName() {
                  var fname = document.getElementById('fname').value;
                  var lname = document.getElementById('lname').value;
                  var full = lname + ' ' + fname;
      
                  document.getElementById('fullname').value = full;
                  document.getElementById('submit-btn').style.display = 'block';
      
                  return full;
              }
      
              document.addEventListener("DOMContentLoaded", function () {
      
                  new QWebChannel(qt.webChannelTransport, function (channel) {
                      //alert('111 channel=' + channel )
      
                      window.bridge = channel.objects.bridge;
                      alert('bridge=' + bridge + '\n从pyqt传来的参数=' + window.bridge.strValue);
      
                  });
              });
      
              function onShowMsgBox() {
                  //alert('window.bridge=' + window.bridge);
      
                  if (window.bridge) {
                      //alert('bridge.strValue=' + window.bridge.strValue ) ;
                      //bridge.sayHello('999')
                      var fname = document.getElementById('fname').value;
                      window.bridge.strValue = fname;
      
      
                  }
      
              }
      
      
          script>
      head>
      
      <body>
      <form>
          <label for="姓名">user name:label>
          <input type="text" name="fname" id="fname">input>
          <br/>
          <input type="button" value="传递参数到pyqt" onclick="onShowMsgBox()">
          <input type="reset" value='重置'/>
      form>
      body>
      html>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57

      在这里插入图片描述

    4. 实例

      from PyQt5.QtWidgets  import QApplication , QWidget , QVBoxLayout 
      from PyQt5.QtWebEngineWidgets import QWebEngineView
      from PyQt5.QtCore import QUrl  
      from MySharedObject  import MySharedObject
      from PyQt5.QtWebChannel import  QWebChannel 
      import sys
      from pyqt5_plugins.examples.exampleqmlitem import QtCore
      QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
      
      # 创建一个 application实例
      app = QApplication(sys.argv)
      win = QWidget()
      win.setWindowTitle('Web页面中的JavaScript与 QWebEngineView交互例子')
      
      # 创建一个垂直布局器
      layout = QVBoxLayout()
      win.setLayout(layout)
      
      # 创建一个 QWebEngineView 对象
      view =  QWebEngineView()
      htmlUrl = 'http://127.0.0.1:8000/web/index.html'
      view.load( QUrl( htmlUrl ))
      
      # 创建一个 QWebChannel对象,用来传递pyqt参数到JavaScript
      channel =  QWebChannel( )
      myObj = MySharedObject()   
      channel.registerObject( "bridge", myObj )  
      view.page().setWebChannel(channel)
       
      # 把QWebView和button加载到layout布局中
      layout.addWidget(view)
                 
      # 显示窗口和运行app
      win.show()
      sys.exit(app.exec_())
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35

      MySharedObject.py

      from PyQt5.QtCore import QObject
      from PyQt5.QtCore import pyqtProperty
      from PyQt5.QtWidgets import QWidget,QMessageBox
      
      class MySharedObject(QWidget):
              
         def __init__( self):
            super( MySharedObject, self).__init__()
                        
         def _getStrValue( self):
              #  
            return '100'        
      
         def _setStrValue( self,  str ):
              #  
            print('获得页面参数 :%s'% str ) 
            QMessageBox.information(self,"Information", '获得页面参数 :%s'% str )
              
          #需要定义对外发布的方法    
         strValue = pyqtProperty(str, fget=_getStrValue, fset=_setStrValue)     
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20

    在这里插入图片描述

  • 相关阅读:
    六、e2studio VS STM32CubeIDE之代码自动补全
    和运维工程师聊完,发现小丑竟是我自己
    计算机毕业设计Java物流信息管理系统(源码+系统+mysql数据库+Lw文档)
    计算机专业英语
    vue.js样式绑定03(源代码)
    SpringCloud: RestTemplate 带header发送post请求
    网络流媒体协议的联系与区别(RTP RTCP RTSP RTMP HLS)
    SQL语言-关系数据库的标准语言
    总结Kibana DevTools如何操作elasticsearch的常用语句
    Java多线程-ThreadPool线程池-1(三)
  • 原文地址:https://blog.csdn.net/weixin_44226181/article/details/126038787