How can I get the maximum and current value of the verticalScrollBar when displaying html with QWebEngineView

前端 未结 1 669
情书的邮戳
情书的邮戳 2021-01-25 03:45

I\'m attempting to create a UI in Maya (Python 2.7.11 and Maya Qt 5.6.1. and PySide2) where the OK button is grayed out until the user scrolls to the bottom. I can do this easil

相关标签:
1条回答
  • 2021-01-25 04:20

    In the case you want to get some information from the DOM you have to do it with javascript, in this case we will create an object that will have the required information and export it to the HTML so that each time the scroll status changes it will be updated.

    from PySide2 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 YScrollBarListener(Element):
        valueChanged = QtCore.Signal(int)
        maximumChanged = QtCore.Signal(int)
    
        def __init__(self, name, parent=None):
            super(YScrollBarListener, self).__init__(name, parent)
            self._value = -1
            self._maximum = -1
    
        @QtCore.Property(int, notify=valueChanged)
        def value(self):
            return self._value
    
        @QtCore.Property(int, notify=maximumChanged)
        def maximum(self):
            return self._maximum
    
        def script(self):
            _script = '''
            window.addEventListener("scroll", function(event){
                {{name}}.update_value(this.scrollY);
                // https://stackoverflow.com/a/43571388/6622587
                var scrollMaxY = window.scrollMaxY || (document.documentElement.scrollHeight - document.documentElement.clientHeight)
                {{name}}.update_maximum(scrollMaxY)
            });
            '''
            return Template(_script).render(name=self.name)
    
        @QtCore.Slot(int)
        def update_value(self, value):
            if self._value != value:
                self._value = value
                self.valueChanged.emit(value)
    
        @QtCore.Slot(int)
        def update_maximum(self, maximum):
            if self._maximum != maximum:
                self._maximum = maximum
                self.maximumChanged.emit(maximum)
    
    class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
        def __init__(self, *args, **kwargs):
            super(WebEnginePage, self).__init__(*args, **kwargs)
            self.loadFinished.connect(self.onLoadFinished)
            self._objects = []
    
        def add_object(self, obj):
            self._objects.append(obj)
    
        @QtCore.Slot(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 Widget(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
    
            self._scrollbar_listener = YScrollBarListener("y_scrollbar_listener", self)
            self._scrollbar_listener.valueChanged.connect(self.on_y_value_changed)
            view = QtWebEngineWidgets.QWebEngineView()
            page = WebEnginePage(view)
            page.add_object(self._scrollbar_listener)
            view.setPage(page)
    
            view.load(QtCore.QUrl("https://stackoverflow.com/questions/43282899"))
    
            self._button = QtWidgets.QPushButton("button")
            progressbar = QtWidgets.QProgressBar(maximum=100)
            view.loadProgress.connect(progressbar.setValue)
    
            lay = QtWidgets.QVBoxLayout(self)
            lay.addWidget(view)
            lay.addWidget(self._button)
            lay.addWidget(progressbar)
    
            self.resize(640, 480)
    
        def on_y_value_changed(self, value):
            self._button.setEnabled(self._scrollbar_listener.maximum != value)
    
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        app.setStyle('fusion')
        app.setStyleSheet('''
        QPushButton
        {
            background-color: #2E8B57;
        }
        QPushButton:disabled
        {
            background-color: #FFFAFA;
        }
        ''')
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    
    0 讨论(0)
提交回复
热议问题