返回信息流刚接触QT,想试试这个addToJavaScriptWindowObject,但是发现没有效果
查了很久,没发现错误所在,请大家帮忙看看
py代码:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWebKit import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebKitWidgets import *
import sys
class Test(QObject):
@pyqtSlot(str, str,str)
def test(self):
print('x')
return 'x'
@pyqtSlot()
def regist_service():
frame.addToJavaScriptWindowObject('Test', Test())
@pyqtSlot(str)
def on_title_changed(title):
web.setWindowTitle(title)
app = QApplication(sys.argv)
web = QWebView()
web.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
frame = web.page().mainFrame()
frame.javaScriptWindowObjectCleared.connect(regist_service)
web.setUrl(QUrl('http://localhost:63342/byr/index.html'))
web.titleChanged.connect(on_title_changed)
web.show()
app.exec_()
html里的js:
<script>
alert('x2');
Test.test();
alert('x2');
</script>
运行的时候只运行到了第一个alert('x2),第二个就运行不了了,python里也没有print
代码参考自
http://www.oschina.net/code/snippet_116913_11423
把service下的方法修改成简单的print
@Slot在pyqt5下找不到,改成了pyqtSlot,对qt里槽和信号不是很懂,不知道这里
定义这个是做什么用的
看了其他语言的qt,也没发现错误在哪里
http://blog.csdn.net/myaccella/article/details/6956534
这是一条镜像帖。来源:北邮人论坛 / python / #6360同步于 2015/4/18
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖
pyqt中addToJavaScriptWindowObject的问题
Ncer
2015/4/18镜像同步7 回复
订阅后,新回复会通过你的通知中心匿名送达。
7 条回复
【 在 Ncer 的大作中提到: 】
: 刚接触QT,想试试这个addToJavaScriptWindowObject,但是发现没有效果
: 查了很久,没发现错误所在,请大家帮忙看看
: py代码:
: ...................
看样子问题出在Python的垃圾回收器把那个Test实例回收了。Python看到Test对象在test函数里创建,又没有在别的地方保存引用,于是就把它回收了。
怎么说呢,Qt的addToJavaScriptWindowObject方法的默认的所有制规则是QtOwnership,也就是Qt管理内存,让WebKit不要去管它。这下好了,Python自作聪明地把对象删了。但试着改成别的也没用。所以不如干脆让Python程序来手动管理它的生命周期吧。
谢谢暖神!
可是“让Python程序来手动管理它的生命周期吧。”是什么意思呢?
我修改了一下,在Test类定义完后马上实例化了一个变量a,
然后在窗口销毁后调用a.test()
这样的话a是不是在窗口销毁前都一直存活着?
可是这样也没有效果
class Test(QObject):
@pyqtSlot(str,str,str)
def test(self):
print('x')
return 'x'
a = Test()
@pyqtSlot()
def regist_service():
frame.addToJavaScriptWindowObject('Test', a)
@pyqtSlot(str)
def on_title_changed(title):
web.setWindowTitle(title)
app = QApplication(sys.argv)
web = QWebView()
web.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
frame = web.page().mainFrame()
frame.javaScriptWindowObjectCleared.connect(regist_service)
web.setUrl(QUrl('http://localhost:63342/byr/index.html'))
web.titleChanged.connect(on_title_changed)
web.show()
app.exec_()
a.test()
【 在 nuanyangyang 的大作中提到: 】
:
: 看样子问题出在Python的垃圾回收器把那个Test实例回收了。Python看到Test对象在test函数里创建,又没有在别的地方保存引用,于是就把它回收了。
: 怎么说呢,Qt的addToJavaScriptWindowObject方法的默认的所有制规则是QtOwnership,也就是Qt管理内存,让WebKit不要去管它。这下好了,Python自作聪明地把对象删了。但试着改成别的也没用。所以不如干脆让Python程序来手动管理它的生命周期吧。
我描述的不对,就是js只alert了一次,而如果正常的话js应该alert两次才对
【 在 nuanyangyang (暖羊羊) 的大作中提到: 】
: 什么叫“运行不了”呢?报什么错?
通过『我邮2.0』发布
【 在 Ncer 的大作中提到: 】
: 谢谢暖神!
: 可是“让Python程序来手动管理它的生命周期吧。”是什么意思呢?
: 我修改了一下,在Test类定义完后马上实例化了一个变量a,
: ...................
Python和C++都有自己的内存管理机制。
C++的话,栈分配、堆分配都可以,堆分配可以自行new和delete,也可以让Qt来帮你管理(有“所有制”之类的机制)。
Python的话,有垃圾回收,而人们一般用的官方Python是用引用计数。关键就是让Python知道什么时候回收这个对象。看样子,Python回收这个对象的时候,还不知道Qt还在使用这个对象。总之,是Python、Qt、WebKit用的内存管理方式不一致造成的混乱。
你那个pyqtSlot标注得有问题。这个方法没有参数,但你这样写的意思是有3个参数,都是str。你可以写pyqtSlot(result=str)
啊啊啊谢谢暖神!
修改pyqtSlot之后可以了!
所以之前的问题是:
1、addToJavaScriptWindowObject注册的Test类还没使用就被python回收掉了
2、pyqtSlot写得不对
对应解决方法:
1、实例化一个对象,再把这个对象注册给webview
2、按对应的函数修改pyqtslot
【 在 nuanyangyang 的大作中提到: 】
:
: Python和C++都有自己的内存管理机制。
: C++的话,栈分配、堆分配都可以,堆分配可以自行new和delete,也可以让Qt来帮你管理(有“所有制”之类的机制)。
: ...................