问题
I am working with pyqt5. I want the user to click on the browser which should be embeded on my pyqt5 application to get the Class of the element which he/she is clicking on it.
I just found on stack overflow that it's doable by combining javascript code with python. Any idea how to extract the class of the element?
回答1:
The solution is to add an "event listener" that makes possible communication between the DOM objects and (Py)Qt.
The following solution is based on this answer.
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel
from jinja2 import Template
class Element(QtCore.QObject):
def __init__(self, name, parent=None):
super(Element, self).__init__(parent)
self._name = name
@property
def name(self):
return self._name
def script(self):
return ""
class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
def __init__(self, parent=None):
super(WebEnginePage, self).__init__(parent)
self.loadFinished.connect(self.onLoadFinished)
self._objects = []
self._scripts = []
def add_object(self, obj):
self._objects.append(obj)
@QtCore.pyqtSlot(bool)
def onLoadFinished(self, ok):
print("Finished loading: ", ok)
if ok:
self.load_qwebchannel()
self.add_objects()
def load_qwebchannel(self):
file = QtCore.QFile(":/qtwebchannel/qwebchannel.js")
if file.open(QtCore.QIODevice.ReadOnly):
content = file.readAll()
file.close()
self.runJavaScript(content.data().decode())
if self.webChannel() is None:
channel = QtWebChannel.QWebChannel(self)
self.setWebChannel(channel)
def add_objects(self):
if self.webChannel() is not None:
objects = {obj.name: obj for obj in self._objects}
self.webChannel().registerObjects(objects)
_script = """
{% for obj in objects %}
var {{obj}};
{% endfor %}
new QWebChannel(qt.webChannelTransport, function (channel) {
{% for obj in objects %}
{{obj}} = channel.objects.{{obj}};
{% endfor %}
});
"""
self.runJavaScript(Template(_script).render(objects=objects.keys()))
for obj in self._objects:
if isinstance(obj, Element):
self.runJavaScript(obj.script())
class Helper(Element):
classClicked = QtCore.pyqtSignal(str)
def script(self):
js = """
document.addEventListener('click', function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
{{name}}.objectClicked(target.className);
}, false);"""
return Template(js).render(name=self.name)
@QtCore.pyqtSlot(str)
def objectClicked(self, className):
if className:
self.classClicked.emit(className)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
classname_helper = Helper("classname_helper")
classname_helper.classClicked.connect(lambda name: print("clicked", name))
view = QtWebEngineWidgets.QWebEngineView()
page = WebEnginePage()
page.add_object(classname_helper)
view.setPage(page)
view.load(QtCore.QUrl("https://stackoverflow.com/questions/60524774"))
view.show()
sys.exit(app.exec_())
来源:https://stackoverflow.com/questions/60524774/is-there-any-way-to-get-class-of-the-page-in-pyqt5-in-browser