C'est une vieille question, mais...
Pour exécuter des fonctions PyQt à partir de javascript :
Bien qu'il y ait de nombreuses façons de procéder, j'ai résolu le problème en utilisant QWebChannel
et ensuite appeler les fonctions js à partir de votre html, puis utiliser le canal web pour communiquer avec Qt.
Vous aurez besoin de qwebchannel.js
. J'ai récupéré le mien dans le répertoire des exemples de Qt5 sur ma machine locale. Le même fichier existe sur le web à de nombreux endroits. Je vous laisse le soin de le trouver.
Une grande partie de cette méthode est décrite ici : http://doc.qt.io/qt-5/qtwebchannel-javascript.html
Dans votre __init__
créer un canal web :
self.webchannel = QtWebChannel.QWebChannel(self)
puis configurez la page principale de votre webengineview pour utiliser le canal, et enregistrez l'objet que vous voulez partager entre PyQt et js :
self.page().setWebChannel(self.webchannel)
self.webchannel.registerObject('MyChannel', self)
Dans votre fichier .js (ou dans la section javascript de votre fichier .html), configurez le canal web :
var MyChannel = null;
new QWebChannel(qt.webChannelTransport, function(channel) {
MyChannel = channel.objects.MyChannel;
});
(C'est là que qwebchannel.js
entre en jeu. Votre fichier js ou html doit être capable de l'inclure. Pour moi, j'ai chargé <script src="scripts/qwebchannel.js"></script>
avant de faire tout autre js
Maintenant vous êtes prêt à faire des appels de js à PyQt via le canal, mais que pouvez-vous appeler ? Tout ce qui est décoré comme un slot PyQt. Donc, par exemple, si, en javascript, vous voulez appeler une fonction "foo" dans Render qui prend une chaîne comme argument, alors vous la créerez (comme un membre de Render) comme tel :
@QtCore.pyqtSlot(str)
def foo(self, some_tring):
print ("Some string: %s" % some_string)
...et ensuite dans le fichier js (ou dans votre index.html), vous feriez simplement un appel à MyChannel.foo('whatever')
. Vous pouvez le faire dans le cadre d'un onclick, ou dans le corps d'une autre fonction que vous appelez à partir d'un onclick.
Parler à travers MyChannel.foo('whatever')
: Vous appelez MyChannel
parce que c'est le nom que vous avez assigné à l'objet que vous avez enregistré avec le canal (en python), et le nom que vous avez utilisé en js lorsque vous avez créé l'objet new QWebChannel
. Lorsque vous avez créé l'enregistrement, vous avez transmis self
comme l'objet à enregistrer - ainsi le canal, identifié par MyChannel
est votre Render
objet. Vous ne pouvez émettre un signal qu'à travers le canal, donc tout ce que vous "appelez" doit être un slot - d'où le décorateur.
Sinon, si vous voulez appeler une fonction js à partir de PyQt, c'est un peu plus facile. Dans ce cas, vous appelez simplement
self.page().runJavaScript('someJsFunction("whatever");')
Si vous devez faire quelque chose avec la réponse, parce qu'elle est appelée asynchrone, vous devrez configurer un gestionnaire de réponse :
self.page().runJavaScript('someJsFunction("whatever");', self.__callback)
...et ensuite définir le callback (probablement comme un membre de Render) :
def __callback(self, response):
if response:
print ("Handling JS response: %s", response)