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.1\Lib\site-packages\pyqt5_tools\Qt\bin\desinger.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

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM