PyQt5:QWebEngineView 中的鼠标点击和源代码
PyQt5: mouseClick and source-code in QWebEngineView
我有一个使用 PyQt-5.5.1 的工作脚本,我现在想将其移植到新的 PyQt 版本 (5.7)。调整大部分内容都很好,但我遇到了两个主要问题:(1) 执行(模拟)鼠标点击,(2) 访问(比方说:打印)网页的 html 源代码当前分别显示在QWebView或QWebEngineView中。
例如,我可以使用 PyQt-5.5.1 中的 QWebView 执行以下操作:
QTest.mouseClick(self.wvTest, Qt.LeftButton, QPoint(x, y))
和
frame = self.wvTest.page().mainFrame()
print(frame.toHtml().encode('utf-8'))
我知道 docs as well as this page 关于移植到 QWebEngineView 但无法将 C++ 表示法转换为工作 Python 代码。
我怎样才能使它适应 PyQt-5.7 中的 QWebEngineView?下面是 PyQt-5.5.1 的完整工作片段,它对于新的 PyQt 版本失败:
- 对于 Button1:根本没有鼠标点击反应。
- 对于 Button2:
AttributeError: 'QWebEnginePage' object has no attribute 'mainFrame'
,当我删除 mainframe() 时:TypeError: toHtml(self, Callable[..., None]): not enough arguments
.
导入系统
来自 PyQt5.QtWidgets 导入 QWidget、QPushButton、QApplication
来自 PyQt5.QtCore 导入 QRect、Qt、QUrl、QPoint、QEvent
来自 PyQt5.QtTest 导入 QTest
从 PyQt5.Qt 导入 PYQT_VERSION_STR
if PYQT_VERSION_STR=='5.5.1': 从 PyQt5 导入 QtWebKitWidgets
否则:从 PyQt5 导入 QtWebEngineWidgets
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.button1 = QPushButton('Button1', self)
self.button1.clicked.connect(self.buttonOne)
self.button1.setGeometry(QRect(10, 10, 90, 20))
self.button2 = QPushButton('Button2', self)
self.button2.clicked.connect(self.buttonTwo)
self.button2.setGeometry(QRect(110, 10, 90, 20))
if PYQT_VERSION_STR=='5.5.1': self.wvTest = QtWebKitWidgets.QWebView(self)
else: self.wvTest = QtWebEngineWidgets.QWebEngineView(self)
self.wvTest.setGeometry(QRect(10, 40, 430, 550))
self.wvTest.setUrl(QUrl('http://www.startpage.com'))
self.wvTest.setObjectName('wvTest')
self.setGeometry(300, 300, 450, 600)
self.setWindowTitle('WebView minimalistic')
self.show()
def buttonOne(self):
qp = QPoint(38, 314)
QTest.mouseClick(self.wvTest, Qt.LeftButton, pos=qp) # or: QTest.mouseMove(self.wvTest, pos=self.qp)
print('Button1 pressed.')
def buttonTwo(self):
frame = self.wvTest.page().mainFrame()
print(frame.toHtml().encode('utf-8'))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
QWebEngineView
class 不是 QWebView
的直接替代品。正如 porting guide 所表明的那样,许多 API 已经发生了根本性的变化,一些主要功能完全缺失。这可能会导致无法编写兼容层,除非您的浏览器实现非常非常简单。编写单独的测试套件很可能会更容易(除非您不介意编写大量条件代码)。
首先,您需要为 QTBUG-43602 实施变通办法。 QWebEngineView
的当前设计意味着内部 QOpenGLWidget
处理鼠标事件,因此无论何时加载页面,您的代码都需要获取对它的新引用:
class Example(QWidget):
...
def initUI(self):
...
self._glwidget = None
if PYQT_VERSION_STR=='5.5.1':
self.wvTest = QtWebKitWidgets.QWebView(self)
else:
self.wvTest = QtWebEngineWidgets.QWebEngineView(self)
self.wvTest.installEventFilter(self)
...
def eventFilter(self, source, event):
if (event.type() == QEvent.ChildAdded and
source is self.wvTest and
event.child().isWidgetType()):
self._glwidget = event.child()
self._glwidget.installEventFilter(self)
elif (event.type() == QEvent.MouseButtonPress and
source is self._glwidget):
print('web-view mouse-press:', event.pos())
return super().eventFilter(source, event)
def buttonOne(self):
qp = QPoint(38, 314)
widget = self._glwidget or self.wvTest
QTest.mouseClick(widget, Qt.LeftButton, pos=qp)
为了访问页面的 html,您需要一些条件代码,因为网络引擎 API 异步工作,需要回调。此外,在网络引擎中没有用于处理帧的内置 APIs(你需要为此使用 javascript),所以一切都需要通过网页:
def buttonTwo(self):
if PYQT_VERSION_STR=='5.5.1':
print(self.wvTest.page().toHtml())
else:
self.wvTest.page().toHtml(self.processHtml)
def processHtml(self, html):
print(html)
我有一个使用 PyQt-5.5.1 的工作脚本,我现在想将其移植到新的 PyQt 版本 (5.7)。调整大部分内容都很好,但我遇到了两个主要问题:(1) 执行(模拟)鼠标点击,(2) 访问(比方说:打印)网页的 html 源代码当前分别显示在QWebView或QWebEngineView中。
例如,我可以使用 PyQt-5.5.1 中的 QWebView 执行以下操作:
QTest.mouseClick(self.wvTest, Qt.LeftButton, QPoint(x, y))
和
frame = self.wvTest.page().mainFrame()
print(frame.toHtml().encode('utf-8'))
我知道 docs as well as this page 关于移植到 QWebEngineView 但无法将 C++ 表示法转换为工作 Python 代码。
我怎样才能使它适应 PyQt-5.7 中的 QWebEngineView?下面是 PyQt-5.5.1 的完整工作片段,它对于新的 PyQt 版本失败:
- 对于 Button1:根本没有鼠标点击反应。
- 对于 Button2:
AttributeError: 'QWebEnginePage' object has no attribute 'mainFrame'
,当我删除 mainframe() 时:TypeError: toHtml(self, Callable[..., None]): not enough arguments
.
导入系统 来自 PyQt5.QtWidgets 导入 QWidget、QPushButton、QApplication 来自 PyQt5.QtCore 导入 QRect、Qt、QUrl、QPoint、QEvent 来自 PyQt5.QtTest 导入 QTest 从 PyQt5.Qt 导入 PYQT_VERSION_STRif PYQT_VERSION_STR=='5.5.1': 从 PyQt5 导入 QtWebKitWidgets 否则:从 PyQt5 导入 QtWebEngineWidgets
class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.button1 = QPushButton('Button1', self) self.button1.clicked.connect(self.buttonOne) self.button1.setGeometry(QRect(10, 10, 90, 20)) self.button2 = QPushButton('Button2', self) self.button2.clicked.connect(self.buttonTwo) self.button2.setGeometry(QRect(110, 10, 90, 20)) if PYQT_VERSION_STR=='5.5.1': self.wvTest = QtWebKitWidgets.QWebView(self) else: self.wvTest = QtWebEngineWidgets.QWebEngineView(self) self.wvTest.setGeometry(QRect(10, 40, 430, 550)) self.wvTest.setUrl(QUrl('http://www.startpage.com')) self.wvTest.setObjectName('wvTest') self.setGeometry(300, 300, 450, 600) self.setWindowTitle('WebView minimalistic') self.show() def buttonOne(self): qp = QPoint(38, 314) QTest.mouseClick(self.wvTest, Qt.LeftButton, pos=qp) # or: QTest.mouseMove(self.wvTest, pos=self.qp) print('Button1 pressed.') def buttonTwo(self): frame = self.wvTest.page().mainFrame() print(frame.toHtml().encode('utf-8')) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_())
QWebEngineView
class 不是 QWebView
的直接替代品。正如 porting guide 所表明的那样,许多 API 已经发生了根本性的变化,一些主要功能完全缺失。这可能会导致无法编写兼容层,除非您的浏览器实现非常非常简单。编写单独的测试套件很可能会更容易(除非您不介意编写大量条件代码)。
首先,您需要为 QTBUG-43602 实施变通办法。 QWebEngineView
的当前设计意味着内部 QOpenGLWidget
处理鼠标事件,因此无论何时加载页面,您的代码都需要获取对它的新引用:
class Example(QWidget):
...
def initUI(self):
...
self._glwidget = None
if PYQT_VERSION_STR=='5.5.1':
self.wvTest = QtWebKitWidgets.QWebView(self)
else:
self.wvTest = QtWebEngineWidgets.QWebEngineView(self)
self.wvTest.installEventFilter(self)
...
def eventFilter(self, source, event):
if (event.type() == QEvent.ChildAdded and
source is self.wvTest and
event.child().isWidgetType()):
self._glwidget = event.child()
self._glwidget.installEventFilter(self)
elif (event.type() == QEvent.MouseButtonPress and
source is self._glwidget):
print('web-view mouse-press:', event.pos())
return super().eventFilter(source, event)
def buttonOne(self):
qp = QPoint(38, 314)
widget = self._glwidget or self.wvTest
QTest.mouseClick(widget, Qt.LeftButton, pos=qp)
为了访问页面的 html,您需要一些条件代码,因为网络引擎 API 异步工作,需要回调。此外,在网络引擎中没有用于处理帧的内置 APIs(你需要为此使用 javascript),所以一切都需要通过网页:
def buttonTwo(self):
if PYQT_VERSION_STR=='5.5.1':
print(self.wvTest.page().toHtml())
else:
self.wvTest.page().toHtml(self.processHtml)
def processHtml(self, html):
print(html)