前言
之前一直在开发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_())
通过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;
}


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对象的父子关系操作
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类型判定
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_())
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_())
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的位置和大小信息
控件以左上角为坐标原点,向右为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()
多线程


'''
多线程更新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_())
加载本地的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_())
嵌入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_())
以上我们主要学习了如何使用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_())
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_())
==============


<!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>
来源:oschina
链接:https://my.oschina.net/u/4405407/blog/4535871