问题
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 easily with QTextEdit by grabbing the value and maximum from the verticalScrollBar but I can't seem to find similar objects in QWebEngineView or QWebEnginePage. Any Ideas?
回答1:
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_())
来源:https://stackoverflow.com/questions/55290759/how-can-i-get-the-maximum-and-current-value-of-the-verticalscrollbar-when-displa