我正在尝试在Maya(Python 2.7.11和Maya Qt 5.6.1。和PySide2)中创建UI,在该UI中,“确定”按钮显示为灰色,直到用户滚动到底部。我可以通过从verticalScrollBar抓取值和最大值来轻松实现QTextEdit的功能,但在QWebEngineView或QWebEnginePage中似乎找不到类似的对象。有任何想法吗?
答案 0 :(得分:0)
如果要从DOM中获取一些信息,则必须使用javascript进行处理,在这种情况下,我们将创建一个具有所需信息的对象,并将其导出到HTML,以便每次滚动状态更改将对其进行更新。
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_())