使用QWebEngineView显示html时如何获取verticalScrollBar的最大值和当前值
Posted
技术标签:
【中文标题】使用QWebEngineView显示html时如何获取verticalScrollBar的最大值和当前值【英文标题】:How can I get the maximum and current value of the verticalScrollBar when displaying html with QWebEngineView 【发布时间】:2019-03-21 23:33:23 【问题描述】:我正在尝试在 Maya(Python 2.7.11 和 Maya Qt 5.6.1. 和 PySide2)中创建一个 UI,其中“确定”按钮显示为灰色,直到用户滚动到底部。我可以通过从verticalScrollBar 中获取值和最大值来使用QTextEdit 轻松完成此操作,但我似乎无法在QWebEngineView 或QWebEnginePage 中找到类似的对象。有什么想法吗?
【问题讨论】:
哦,我以为我在星期五留下了评论。我能够运行代码,但遇到了一个破坏滚动检测功能的 unicode 错误。另一个问题是我真的不想使用 jinja2 并且由于正在加载的页面是本地文件,我可以将 javascript 嵌入页面中,而不是在加载时将其即时添加到页面。跨度> 这是错误:code ('Finished loading: ', True) Traceback (most recent call last): File "scrool.py", line 69, in onLoadFinished self.load_qwebchannel() File "scrool.py", line 77, in load_qwebchannel self.runJavaScript(content.data().decode()) UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 152: ordinal not in range(128)
Maya 使用 Python 2
您提供的网址有错误
在 Maya 推出使用 3 的版本之前,我将坚持使用 2.7,但我也没想到这项特殊任务会像事实证明的那样棘手。
【参考方案1】:
如果您想从 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://***.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://***.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_())
【讨论】:
以上是关于使用QWebEngineView显示html时如何获取verticalScrollBar的最大值和当前值的主要内容,如果未能解决你的问题,请参考以下文章
如何在 QWebEngineView 中禁用工具提示(标题)的自动换行
如何在使用 QWebEngineView 'loadFinished' 加载页面后立即更改 html 元素?
使用 QWebEngineView 时如何防止创建奇怪的文件夹?