python - 使用QWebEngineView显示html时如何获取verticalScrollBar的最大值和当前值
问题描述
我正在尝试在 Maya(Python 2.7.11 和 Maya Qt 5.6.1。和 PySide2)中创建一个 UI,其中 OK 按钮显示为灰色,直到用户滚动到底部。我可以通过从verticalScrollBar 中获取值和最大值来使用QTextEdit 轻松完成此操作,但我似乎无法在QWebEngineView 或QWebEnginePage 中找到类似的对象。有任何想法吗?
解决方案
如果您想从 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_())
推荐阅读
- python - 如何计算 K 折交叉验证中所有折的分类报告中的平均值?
- electron - 为什么电子不创建文件?
- xml - Paraview:以 VTK-XML 存储表示
- dask - 有效地将每个组的附加信息传递给 Dask dataframe.groupby.apply 函数
- python-3.x - 在 Windows 10 上使用 tkinter 在后台为 GUI 运行控制台窗口
- python - Pandas:基于列名的列中位数
- android - Android Kotlin 协程异常
- python - 删除某个字符后的 n 个字符
- json - 如何在 Apache Nifi 中将字符串值转换为数组
- javascript - 如何使用 NodeJS 在特定时间执行发射(socket.io)?