zoukankan      html  css  js  c++  java
  • PyQt5(Python GUI图形化用户接口)

    前言

    之前一直在开发B/S架构的web应用,虽然web应用无需额外安装,但是browser客户端对客户端本机的硬件设备(摄像头、蓝牙设备、打印机、串口...)进行操作。

    如果Python和JavaScript之间的函数可以相互调用就好了,Python+JavaScript融合起来的Client肯定会更加强大。

    PyQt5概述

    Gui:Graphical User Interface又称图形用户接口。也就是我们俗称的桌面应用

    Qt :一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架,支持Windows、Linux、MacOs。

    PyQt5:使用Python对C++的Qt库的重新实现,由于最新Qt版本是5.11所以我们习惯称PyQt为PyQt5。

    安装PyQt5

    pip install PyQt5 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

    安装pyqt5-tools

    安装完pyqt5-tools之后就可以使用desinger了。desinger是一款图形化的UI组织工具。

    pip install pyqt5-tools -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

    desinger.exe路径

    D:Python3.6.1Libsite-packagespyqt5_toolsQtindesinger.exe

     配置desinger.exe

      

    PyQt5程序的基本结构

    0.导入相关模块

    1.创建1个应用程序对象和1个Window窗口

    2.开始在Windows中添加控件、设置控件展示样式、设置控件的信号和槽。

    3.sys.exit(app.exec_()) 进入事件循环监听

    from PyQt5.Qt import *
    import  sys
    
    app=QApplication(sys.argv)
    #创建1个window
    window=QWidget()
    #设置这个window的标题
    window.setWindowTitle("PyQt5初体验")
    #设置window的大小
    window.resize(500,500)
    #设置把该window 放在桌面的位置
    window.move(400,200)
    
    
    #在window中创建1个lable标签
    label=QLabel(window)
    label.setText("Hello Martion")
    label.resize(100,200)
    label.move(200,200)
    
    #显示窗口
    window.show()
    
    #进入消息循环模式
    sys.exit(app.exec_())

    控件是什么? 

    把不同的控件绘制在桌面上就是我们看到的桌面应用,控件接受和响应各种事件(鼠标、键盘)和用户进行交互。 

    控件就相当于前端的HTML标签,不同的标签有相同的属性也有自身独有的特性,是组织GUI界面的最小单位。

    每个控件都是矩形的,他们按Z轴排序(叠加)显示

    控件会被父控件和前面的控件剪切。

    没有父控件的控件称之为窗口(windown/顶层控件)。

    PyQt5的顶层和子控件

    和HTML标签类似PyQt5中的控件也是有层级结构的。

    顶层控件:作为1个窗口进行显示、做为容器承载其他控件。

    子控件:在父级控件之内,作为父级控件的一部分。

    from PyQt5.Qt import *
    import  sys
    
    app=QApplication(sys.argv)
    #创建1个window顶层控件
    window=QWidget()
    #设置这个window顶层控件的标题
    window.setWindowTitle("我是父级控件")
    #设置window顶层控件的大小
    window.resize(500,500)
    #设置把该window顶层控件放在桌面的位置
    window.move(400,200)
    
    
    #在顶层控件中创建1个lable子级标签(继承window标签)
    label=QLabel(window)
    label.setText("我是子控件")
    #设置子标签的大小
    label.resize(100,200)
    #设置把该lable标签放在顶层控件的位置
    label.move(100,200)
    #显示顶层控件之后,子控件也跟随显示。
    window.show()
    #进入消息循环模式
    sys.exit(app.exec_())
    控件嵌套

    PyQt5控件学习过程

    PyQt5框架实现 使用了面向对象设计模式,每1种控件由于不同的类实现,所以我们想要对PyQt5框架进行系统的学习,就要从父类开始一直延伸到不同的子类。

    Qobject 类

    QObject是所有Qt对象的基类,学习PyQt5就从它开始,逐个击破。

    QObject设置ID和属性:

    obj.setObjectName("notice"):给QT对象设置1个唯一的名称,相当于对象的ID

    print(obj.objectName()):获取QT对象的ID

    obj.setProperty("notice_level1","error"):给QT对象动态设置1个属性和值

    print(obj.property("notice_level1")):根据属性名称获取QT对象的值

    print(obj.dynamicPropertyNames()):获取QT对象中所有通过setProperty()设置的属性

    from PyQt5.Qt import *
    
    class Windown(QWidget):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("QObject学习")
            self.resize(500,500)
            self.setup_ui()
    
        def setup_ui(self):
            # self.get_children_of_QObject()
            self.get_property_of_QObject_instance()
            self.get_name_of_QObject_instance()
    
         #获取QObject的子类
        def get_children_of_QObject(self):
            print(QObject.__subclasses__())
    
        #设置和获取QObject 对象的属性
        def get_property_of_QObject_instance(self):
            obj=QObject()
            obj.setProperty("notice_level1","error")
            obj.setProperty("notice_level2", "warning")
            print(obj.property("notice_level1"))
            print(obj.dynamicPropertyNames())
    
        #设置和获取QObject 对象的名称
        def get_name_of_QObject_instance(self):
            obj = QObject()
            obj.setObjectName("notice")
            print(obj.objectName())
    
    if __name__ == '__main__':
        import sys
        app=QApplication(sys.argv)
        window=Windown()
        window.show()
        sys.exit(app.exec_())
    QObject设置ID和属性

    通过ID和属性设置控件的样式

    QLabel#notice{
        font-size:20px;
        color:gray;
        border:1px solid gray;
        border-radius:8px;
    }
    
    QLabel#notice[notice_level="normal"]{
        color:green;
        border-color:green;
    }
    
    QLabel#notice[notice_level="warning"]{
        color:yellow;
        border-color:yellow;
    }
    
    QLabel#notice[notice_level="error"]{
        color:red;
        border-color:red;
    }
    QObject.qss
    from PyQt5.Qt import *
    
    class Windown(QWidget):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("QObject学习")
            self.resize(500,500)
            self.setup_ui()
    
        def setup_ui(self):
            #加载样式文件
            with open("QObject.qss","r") as f:
                qApp.setStyleSheet(f.read())
            label=QLabel(self)
            label.move(150,50)
            label.setText('normal....')
            label.setObjectName("notice")
            label.setProperty("notice_level","normal")
    
            label2=QLabel(self)
            label2.move(150,100)
            label2.setText("warning....")
            label2.setObjectName("notice")
            label2.setProperty("notice_level", "warning")
    
    
    
            label3=QLabel(self)
            label3.setText("error.....")
            label3.move(150,150)
            #设置qt对象ID和属性(和html不同的是ID在整个Qt对象中可以重复!)
            label3.setObjectName("notice")
            label3.setProperty("notice_level", "error")
    
    
            button=QPushButton(self)
            button.setText("提交")
            button.move(150,200)
    
    
    
    if __name__ == '__main__':
        import sys
        app=QApplication(sys.argv)
        window=Windown()
        window.show()
        sys.exit(app.exec_())
    QObject.py

    QObject对象的父子关系操作

    print(p1.parent()):获取父级标签

    print(html.children()):获取所有直接子控件

    #控件2类型、id、FindChildrenRecursively递归查找|FindDirectChildrenOnly仅查找直接节点

    print(html.findChild(QObject, "body",Qt.FindChildrenRecursively)) :筛选子控件(单个)

    print(html.findChildren(QObject,"body")):筛选子控件(多个) 

    from PyQt5.Qt import *
    
    class Windown(QWidget):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("QObject学习")
            self.resize(500,500)
            self.setup_ui()
    
        def setup_ui(self):
            html=QObject()
            body=QObject()
            body.setObjectName("body")
            head=QObject()
            div1=QObject()
            div2=QObject()
            p1 = QObject()
            p2 = QObject()
            #设置父子关系:1个对象只能有1个父级对象,以后设置的为准
            body.setParent(html)
            head.setParent(html)
            div1.setParent(body)
            div2.setParent(body)
            p1.setParent(div1)
            p2.setParent(div2)
    
            #获取父对象
            print(p1.parent())
            #获取所有直接子对象
            print(html.children())
            #控件2类型、id、FindChildrenRecursively递归查找|FindDirectChildrenOnly仅查找直接节点
            print(html.findChild(QObject, "body",Qt.FindChildrenRecursively))
            print(html.findChild(QObject, "body", Qt.FindDirectChildrenOnly))
            #查找多个
            # print(html.findChildren(QObject,"body"))
    
    
    
    
    
    if __name__ == '__main__':
        import sys
        app=QApplication(sys.argv)
        window=Windown()
        window.show()
        sys.exit(app.exec_())
    控件父子关系查找

    如果1个控件没有任何父控件,那么就会当成顶层控件(窗口)。

    如果1个控件有父控件,那么这个子控件的位置受父控件约束,一旦父控件消失子控件也随之消失。

    QObject信号操作

    不管是GUI还是Web编程,都是信号驱动的!这些信号有内置的(click/move/leave....)也可以自定义信号。

    信号和槽是相对而言的,通过PyQt5的QObject类创建的对象可以发出信号,当连接到槽的信号发出时, 槽(函数)就会被调用。

    信号和槽是多对多的关系。一个信号可以连接多个槽,而一个槽也可以监听多个信号。

    流程:

    触发------》信号emit--->connect---->槽起到监听信息,响应用户行为的作用。

    widget.信号.connect(槽) :绑定信号与槽

    obj.disconnect():取消信号与槽绑定

    widget.blockSigals(bool):暂停信号与槽的关系

    widget.signalsBlocked():信号是否暂停

    widget.receives("信号"):objectNameChanged信号对应的接收器(槽)数量

    QObject内置的信号

    obj.destroyed():对象名称发送改变时发射此信号。

    obj.objectNameChanged():对象被销毁时,发射此信号。

    from PyQt5.Qt import *
    
    class Windown(QWidget):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("QObject学习")
            self.resize(500,500)
            self.setup_ui()
        def QObject信号的操作(self):
            obj=QObject()
            def name_changed(name):
                print("对象名称更改为",name)
    
            def name_changed2(name):
                print("The name of object change into", name)
            def destroy_slot(obj):
                print("对象被销毁",obj)
    
            obj.objectNameChanged.connect(name_changed2)
            obj.objectNameChanged.connect(name_changed)
            #解除signal和slot的绑定
            # obj.objectNameChanged.disconnect()
            obj.setObjectName("xx0")
            #暂停信号与槽的关系
            obj.blockSignals(True)
            obj.setObjectName("xx1")
            #恢复信号与槽的关系
            obj.blockSignals(False)
            obj.setObjectName("xx2")
            #objectNameChanged信号对应的接收器(槽)数量
            print(obj.receivers(obj.objectNameChanged))
            obj.destroyed.connect(destroy_slot)
    
        def setup_ui(self):
           self.QObject信号的操作()
    
    
    
    
    
    if __name__ == '__main__':
        import sys
        app=QApplication(sys.argv)
        window=Windown()
        window.show()
        sys.exit(app.exec_())
    QObject信号的操作

    QObject类型判定

    print(obj.isWidgetType()):判断是否为WidgetType

    print(obj.inherits("QWidget")):判断是否继承QWidget

    print(obj.inherits("QPushButton")):判断是否继承QPushButton

    label1=QLabel(self)
            label1.setText("社会我顺哥")
            label1.move(150,100)
            label2=QLabel(self)
            label2.setText("社会我旺哥")
            label2.move(150,150)
            btn=QPushButton(self)
            btn.setText("点我")
            btn.move(150,200)
            #查询所有windown中的子控件
            for wdiget in self.children():
                #把QLabel类型的控件设置为绿色
                if wdiget.inherits("QLabel"):
                    wdiget.setStyleSheet("background-color:green;")
    查询特定类型的子控件

    QObject对象删除

    obj.deleteLater

    机制:删除1个对象时先解除它与父对象的关系,然后向主消息循环发送1个event,下一次消息循环接收到这个event之后,对象被销毁。

    延迟删除的好处在于保证本次消息循环代码不报错,坏处是无法及时释放内存。

    Qt事件机制

    因为信号封装了事件机制,所有用户在PyQt5程序界面的各种操作,就会触发信号进而执行槽函数。

    一个PyQt5应用包含2个消息队列(系统产生的消息、程序内部产生的消息),  应用程序的消息循环就是在不断得处理这些队列中的消息。

    1.用户操作会产生各种事件

    2.第一个接收到消息是操作系统、操作系统将消息分发到对应应用程序的消息队列中。

    3.PyQt程序消息循环如果发现“消息事件”则会包装成QEvent对象,进行分发。

    4.把事件接收者(receiver)和事件对象(evt)传递给QAppplication对象的notify(receiver,evt)方法。

    5.notify方法调用事件接收者的event(event)方法

    6.事件接收者的event方法会根据具体的事件类型,分发给事件接收者 具体的事件函数。

    7.事件函数发送信号执行槽函数。

    import sys
    from PyQt5.Qt import *
    
    class App(QApplication):
        #4.
        def notify(self, recevier,evt):
            if recevier.inherits("QPushButton") and evt.type()==QEvent.MouseButtonPress:
                print(recevier,evt)
    
            return super().notify(recevier,evt)
    
    class Btn(QPushButton):
        #5.
        def event(self, event):
            if event.type()==QEvent.MouseButtonPress:
                print(event)
            return super().event(event)
        #6.
        def mousePressEvent(self, *args,**kwargs):
            print("鼠标被按下了!")
            return super().mousePressEvent(*args,**kwargs)
    
    app=App(sys.argv)
    
    window=QWidget()
    btn=Btn(window)
    btn.setText("按钮")
    btn.move(100,100)
    def func():
        print("按钮被点击了")
    
    
    
    btn.pressed.connect(func)
    
    window.show()
    
    
    sys.exit(app.exec_())
    PyQt5事件机制

    QObject定时器

    timer_id=obj.startTimer(1000):开启定时器,间隔1000毫秒执行1次

    timerEvent(self, timerEvent):定时器定时执行的事件

    obj.killTimer(timer_id):停止某个定时器

    from PyQt5.Qt import *
    import sys
    
    #2.定时执行(继承QObject然后重写timerEvent方法)
    class MyLabel(QLabel):
        #
        def __init__(self,*args,**kwargs):
            super().__init__(*args,**kwargs)
            self.setText("10")
            self.move(100, 100)
            self.setStyleSheet("background-color:yellow;font-size:22px")
            # label继续于Qobject
            self.timer_id1 = self.startTimer(1000)
    
        def timerEvent(self, *args,**kwargs):
            #获取当前标签的大小和内容
            self.resize(self.width()+10,self.height()+10)
            present_second=int(self.text())
            present_second-=1
            self.setText(str(present_second))
            if present_second==0:
                self.killTimer(self.timer_id1)
    
    
    #0.创建1个应用程序对象
    app=QApplication(sys.argv)
    
    window=QWidget()
    window.setWindowTitle("QObject定时器的使用")
    window.resize(500,500)
    
    label=MyLabel(window)
    
    
    
    
    
    obj=QObject()
    #1.间隔1秒钟就会执行obj的startTimer()方法
    timer_id=obj.startTimer(1000)
    #3.使用obj的killTimer(timer_id)方法停止某1个定时器
    obj.killTimer(timer_id)
    
    window.show()
    sys.exit(app.exec_())
    QObject定时器

    QWidget类

    Qwidget是QOject的子类(QObject的方法它全部具备), QWidget可以绘制1个最基本、简单的空白控件(div),是所有可视化控件的基类。

    from PyQt5.Qt import *
    import sys
    
    app=QApplication(sys.argv)
    #没有父控件的控件就是窗口
    window=QWidget()
    window.setWindowTitle("QObject定时器的使用")
    window.resize(500,500)
    
    #window的子控件1
    red_one=QWidget(window)
    red_one.resize(100,100)
    red_one.setStyleSheet("background-color:red")
    red_one.move(300,0)
    
    #window的子控件2
    green_one=QWidget(window)
    green_one.resize(100,100)
    green_one.setStyleSheet("background-color:green")
    green_one.move(300,100)
    
    #显示窗口
    window.show()
    #进入世界循环
    sys.exit(app.exec_())
    QWidget控件初体验

     

    QWidget的位置和大小信息

    控件以左上角为坐标原点,向右为x轴方向,向下为y轴方向。

    参照位置:如果有父控件就参照父控件,如果是顶级控件就参照整个window。

     

    获取控件的位置和大小

    x():获取相对于父控件的x位置,顶层控件(没有父控件)则相对于桌面的x位置。

    y():获取相对于父控件的y位置,顶层控件(没有父控件)则相对于桌面的x位置。

    pos():获取x和y的组合

    width():获取控件的宽度(用户区域)

    height():获取控件的高度(用户区域)

    size():获取width和height的组合。

    geometry():获取用户区域(不包含窗口) x,y,width和height相当于父控件位置和尺寸组合。

    rect():获取用户区域0,0,width和height的组合

    frameSize():获取框架的大小

    frameGeometry():获取框架的尺寸

    ps:控件显示完毕之后,获取具体的位置或尺寸数据才会正确。

    代码

    from PyQt5.Qt import *
    import sys
    
    app=QApplication(sys.argv)
    #没有父控件的控件就是窗口
    window=QWidget()
    window.setWindowTitle("QObject定时器的使用")
    window.resize(500,500)
    
    #window的子控件1
    red_one=QWidget(window)
    red_one.move(300,0)
    red_one.resize(100,100)
    red_one.setStyleSheet("background-color:red")
    #显示窗口
    window.show()
    
    print(red_one.x())#300
    print(red_one.y())#0
    print(red_one.width())#100
    print(red_one.height())#100
    print(red_one.pos())#PyQt5.QtCore.QPoint(300, 0)
    print(red_one.geometry())#PyQt5.QtCore.QRect(300, 0, 100, 100)
    print(red_one.rect())#PyQt5.QtCore.QRect(0, 0, 100, 100)
    
    #进入世界循环
    sys.exit(app.exec_())

    设置控件的位置和大小

    move():设置控件相对于父控件的x,y也就是pos。

    resize(width,height):设置控件用户区域的宽和高,并非整个框架。

    setGeomerty(x_noFrame,y_noFrame,width,height):设置用户区域距离父控件的位置和宽高。

    adjustSize():根据内容自适应大小。

    setFixedSize():设置固定尺寸。

    import sys
    from PyQt5.Qt import *
    
    app=QApplication(sys.argv)
    
    window=QWidget()
    window.resize(500,500)
    # window.move(300,300)
    
    w=QWidget(window)
    w.resize(100,100)
    w.setStyleSheet("background-color:red")
    
    #总的控件个数
    widget_count=23
    
    #一行有多少列
    colum_count=5
    
    #计算1个控件的宽度
    widget_width=window.width()//colum_count
    #总共有多少行(最大编号//一行有多少列)+1
    row_count=(widget_count-1)//colum_count+1
    #总高度/总行数=单个的高度
    widget_hight=window.height()//row_count
    
    
    
    for i in range(0,widget_count):
        w=QWidget(window)
        w.resize(widget_width,widget_hight)
        #当前控件所在的列号 = 当前控件的编号 %(取于)总列数
        #当前控件所在的行号 =  当前控件的编号 //(整除)总列数
        
        #当前控件说所在的列号 * 控件的宽度
        widget_x=i%colum_count*widget_width
        #当前控件所在的行号 * 控件的高度
        widget_y =i//colum_count * widget_hight
        w.move(widget_x,widget_y)
        w.setStyleSheet("background-color:red;border:1px solid syin")
    
    w.show()
    
    window.show()
    
    
    sys.exit(app.exec_())
    显示表格公式

    设置控件最小、最大尺寸

    windown.resize(500,500):设置弹性最大、最小尺寸

    windown.setFixedSize(500,500):设置固定最大、最小尺寸

    windown.setMinimumSize(200,200):设置最小尺寸(到达这个尺寸之后无法再缩小)

    windown.setMaximumSize(500,500):设置最大尺寸(到达这个尺寸之后无法再缩小)

    windown.setMinimumWidth(300):限定最小/最大的宽度和高度

    windown.setMaximumHeight(400)

    windown.setMaximumWidth(500)

    windown.setMinimumHeight(400)

    一旦设置了固定尺寸/限定了宽度和长度之后,resize() API 将无法修改控件限定范围外的大小。

    调整内容边距

    qlabel.setContentsMargins(10,50,0,0): 设置内容边距顺序为左、上、右、下

    print(qlabel.getContentsMargins()):获取内容边距

    print(qlabel.contentsRect()):获取内容区域

    from PyQt5.Qt import *
    import sys
    
    app=QApplication(sys.argv)
    windown=QWidget()
    windown.setWindowTitle("内容边距")
    windown.resize(500,500)
    
    qlabel=QLabel(windown)
    qlabel.setText("社会我顺哥")
    qlabel.resize(100,100)
    qlabel.setStyleSheet("background-color:cyan;border:1px solid red")
    #设置内容边距:左、上、右、下
    qlabel.setContentsMargins(10,50,0,0)
    #获取内容边距
    print(qlabel.getContentsMargins())
    #获取内容区域
    print(qlabel.contentsRect())
    
    windown.show()
    
    sys.exit(app.exec_())
    调整内容边距

    QWidget鼠标操作

    设置鼠标的形状:缺省情况下我们的鼠标是箭头,但是我们可以改变鼠标的形状。

    window.setCursor(Qt.ArrowCursor) 箭头

    window.setCursor(Qt.UpArrowCursor)向上箭头

    window.setCursor(Qt.CrossCursor) 十字架

    window.setCursor(Qt.IBeamCursor)

    window.setCursor(Qt.WaitCursor)等待

    window.setCursor(Qt.BusyCursor)   繁忙

    window.setCursor(Qt.ForbiddenCursor) 禁止

    window.setCursor(Qt.PointingHandCursor) 手指

    window.setCursor(Qt.WhatsThisCursor)箭头+问号

    window.setCursor(Qt.SizeVerCursor)

    window.setCursor(Qt.SizeHorCursor)

    window.setCursor(Qt.SizeBDiagCursor)

    window.setCursor(Qt.SizeAllCursor)

    window.setCursor(Qt.SplitVCursor)

    window.setCursor(Qt.SplitHCursor)

    window.setCursor(Qt.OpenHandCursor)打开手

    window.setCursor(Qt.ClosedHandCursor) 关闭手

    window.setCursor(Qt.BlankCursor)空白的鼠标

    window.unsetCursor():重置鼠标形状,在改变鼠标形状之后我们还可以将其恢复原样。

    获取鼠标对象

    current_cursor=label.cursor() #获取鼠标对象信息

    print(current_cursor.pixmap())#获取鼠标对象的图片

    current_cursor.setPos(10,100)#设置鼠标位置

    print(current_cursor.pos())#获取鼠标的位置

    鼠标跟踪

    window.setMouseTracking(True):开启鼠标追踪之后会自动触发控件的mouseMoveEven()方法

    自定义信号

    #自定义信号
    
    from PyQt5.QtCore import *
    #信号
    class MyTypeSingnal(QObject):
        #定义1个信号
        sendmsg=pyqtSignal(int)
        def run(self):
            #定义这个信号发出时携带的数据
            self.sendmsg.emit("Hello PyQt5")
    
    #
    class MySlot(QObject):
        #定义1个槽
        def get(self,msg):
            print("信息"+msg)
    
    if __name__ == '__main__':
        signal=MyTypeSingnal()
        slot=MySlot()
        #信号和槽建立连接
        signal.sendmsg.connect(slot.get)
        #触发信号
        signal.run()
        #信号和槽进行解除绑定
        signal.sendmsg.disconnect(slot.get)
        #再次触发信号
        signal.run()
    custom-signal

    多线程

    '''
    多线程更新UI数据
    '''
    import time,sys
    from PyQt5.QtCore import QThread,pyqtSignal,QDateTime
    from PyQt5.QtWidgets import QApplication,QDialog,QLineEdit
    
    class BackendThread(QThread):
        #定义1个信号
        update_date=pyqtSignal(str)
        #信号发出时执行
        def run(self):
            while True:
                time.sleep(1)
                current_date=QDateTime.currentDateTime()
                current_time=current_date.toString("yyyy-MM-dd hh:mm:ss")
                self.update_date.emit(str(current_time))
    
    class ThreadUpdateUI(QDialog):
        def __init__(self):
            QDialog.__init__(self)
            self.setWindowTitle("QT多线程")
            self.resize(100,100)
            self.input=QLineEdit(self)
            self.input.resize(400,100)
            self.initUi()
    
        def initUi(self):
            self.backend=BackendThread()
            #信号--->emit--->connect---->槽
            self.backend.update_date.connect(self.hadleDisplay)
            #触发信号
            self.backend.start()
        #
        def hadleDisplay(self,data):
            self.input.setText(data)
    
    if __name__ == '__main__':
        app=QApplication(sys.argv)
        exaple=ThreadUpdateUI()
        exaple.show()
        sys.exit(app.exec_())
    多线程

    PyQtWebEngine

    PyQtWebEngine实现了Python和JavaScript之间交互,这意味着如果你之前可以开发Web应用就可以开放出一个desptop应用。

    因为这PyQtWebEngine可以把.HTML文件渲染出效果来,也可以把Python嵌入到JavaScript中。

    pip install PyQtWebEngine -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

    加载外部的web界面

    import sys
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtWebEngineWidgets import *
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.setWindowTitle('京东')
            self.setGeometry(5,30,1355,730)
            self.browser=QWebEngineView()
            #加载外部的web界面
            self.browser.load(QUrl('https:www.jd.com'))
            self.setCentralWidget(self.browser)
    
    if __name__ == '__main__':
        app=QApplication(sys.argv)
        win=MainWindow()
        win.show()
        app.exit(app.exec_())
    View Code

     加载本地的HTML文件

    <html>
    
    <body>
    
    <h4>这个表格有一个标题,以及粗边框:</h4>
    <table border="6">
        <caption>我的标题</caption>
        <tr>
            <td onclick="zhanggen()">100</td>
            <td>200</td>
            <td>300</td>
        </tr>
        <tr>
            <td>400</td>
            <td>500</td>
            <td>600</td>
        </tr>
    </table>
    <script>
        function zhanggen() {
            alert(6666)
        }
    </script>
    </body>
    前端
    import sys,os
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtWebEngineWidgets import *
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.setWindowTitle('京东')
            self.setGeometry(5,30,1355,730)
            self.browser=QWebEngineView()
            #加载本地的html文件
            html_path=os.getcwd()+"/index.html"#D:PyQt5模块index.html
            self.browser.load(QUrl.fromLocalFile(html_path))
            self.setCentralWidget(self.browser)
    
    if __name__ == '__main__':
        app=QApplication(sys.argv)
        win=MainWindow()
        win.show()
        app.exit(app.exec_())
    QUrl.fromLocalFile(html_path)

    嵌入HTML字符串

    import os
    import sys
    
    from PyQt5.QtWebEngineWidgets import *
    from PyQt5.QtWidgets import *
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.setWindowTitle('京东')
            self.setGeometry(5, 30, 1355, 730)
            self.browser = QWebEngineView()
            # 加载本地的html文件
            html_path = os.getcwd() + "/index.html"  # D:PyQt5模块index.html
            self.browser.setHtml('''
            <html>
              <body>
                    <h4>这个表格有一个标题,以及粗边框:</h4>
                    <table border="6">
                        <caption>我的标题</caption>
                        <tr>
                            <td onclick="zhanggen()">100</td>
                            <td>200</td>
                            <td>300</td>
                        </tr>
                        <tr>
                            <td>400</td>
                            <td>500</td>
                            <td>600</td>
                        </tr>
                    </table>
                    <script>
                        function zhanggen() {
                            alert(6666)
                        }
                    </script>
                    </body>
            ''')
            self.setCentralWidget(self.browser)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        win = MainWindow()
        win.show()
        app.exit(app.exec_())
    self.browser.setHtml()

    以上我们主要学习了如何使用QtWebEngineWidgets加载出HTML文件的网页效果。下面我们来看看他们之间如何交换数据?

    self.browser.page().runJavaScript

    Python调用JavaScript中的函数

    import sys,os,time
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtWebChannel import QWebChannel
    from PyQt5.QtWebEngineWidgets import QWebEngineView
    
    
    class PyQt5CallJs(QWidget):
        def __init__(self):
            super(PyQt5CallJs,self).__init__()
            self.setWindowTitle('PyQt5调用JavaScript')
            #垂直布局
            self.setGeometry(100,100,400,200)
            self.layout=QVBoxLayout()
            self.setLayout(self.layout)
            #创建浏览器
            self.browser=QWebEngineView()
            html = os.getcwd() + "./templates/test.html"
            self.browser.load(QUrl.fromLocalFile(html))
            self.layout.addWidget(self.browser)
            #绑定clicked事件
            button=QPushButton("开始检测")
            button.clicked.connect(self.progress)
            self.layout.addWidget(button)
    
        #执行
        def progress(self):
            for n in range(0,101):
                self.browser.page().runJavaScript('zhanggen("%s")'%(str(n)),self.progress_callback)
    
    
        #回调
        def progress_callback(self, result):
            print(result)
            # QMessageBox.information(self, "提示", str(result))
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        windown=PyQt5CallJs()
        windown.show()
        sys.exit(app.exec_())
    View Code

    PyQt QtWebChannel

    JavaScript调用Python中的函数

    import sys,os
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtWebChannel import QWebChannel
    from PyQt5.QtWebEngineWidgets import QWebEngineView
    import datetime
    
    class ProgressBar(QWidget):
        def __init__(self):
            super(ProgressBar,self).__init__()
            self.setWindowTitle('进度条')
            self.resize(600,300)
            #创建brwser并使用浏览器加载html文件
            self.browser=QWebEngineView()
            html = os.getcwd() + "./ww.html"
            self.browser.load(QUrl.fromLocalFile(html))
            #在brwser中注册1个Python类的对象
            self.channel = QWebChannel()
            self.channel.registerObject('printer',self)
            self.browser.page().setWebChannel(self.channel)
            #把brwser添加设置到layout里面
            layout = QVBoxLayout()
            layout.addWidget(self.browser)
            self.setLayout(layout)
    
        # pyqtSlot,中文网络上大多称其为槽。作用是接收网页发起的信号
        @pyqtSlot(str, result=str)
        def print(self, content):
            print('输出文本:',content)
            #返回值
            return str(datetime.datetime.now())
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        windown=ProgressBar()
        windown.show()
        sys.exit(app.exec_())
    Python

    ==============

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>测试</title>
        <script src="./qwebchannel.js"></script>
        <!-- 引入qwebchannel.js,才能与QWebEngineView进行交互 -->
        <script type="text/javascript" src="./qwebchannel.js"></script>
        <script>
            window.onload = function () {
                new QWebChannel(qt.webChannelTransport, function (channel) {
                     // 此处channel.objects.printer中的printer就是上文提到的功能类注册的标识名
                    window.printer = channel.objects.printer;
                });
            };
        </script>
    </head>
    <body>
    <button onclick="sendMes()">发送消息</button>
    <p id="mes"></p>
    <script>
        //接收Python函数的返回值
        function callback(result){
            alert(result)
        }
        function sendMes() {  // 调用python端的功能类的方法执行操作
            printer.print('你收到一条网页发送的消息!',callback)
        }
    </script>
    </body>
    </html>
    JavaScript

      

    参考

  • 相关阅读:
    ASP.NET缓存全解析(系列)
    updateprogress用法技巧
    text与img对齐
    9款Firefox插件提高设计开发效率
    ASP.NET页面实时进行GZIP压缩优化
    如何收缩和删除SQL日志文件
    闲扯加班
    与大家分享一点游戏管理晋升的心得(完整版)
    FDS (Flex Data Services)
    和我老婆去旅游
  • 原文地址:https://www.cnblogs.com/sss4/p/13043985.html
Copyright © 2011-2022 走看看