2016-11-19 59 views
4

PyQt-5.5.1を使用する作業スクリプトがあります。これは新しいPyQtバージョン(5.7)に移植したいものです。ほとんどのものを適応させても問題ありませんでしたが、私は2つの大きな問題に直面しました:(1)(シミュレートされた)マウスクリックを実行する、(2)現在表示されているWebページのhtmlソースコードにアクセスそれぞれQWebViewまたはQWebEngineViewと呼ばれます。例えばPyQt5:QWebEngineViewのmouseClickとソースコード

、私は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')) 

私はQWebEngineViewへの移植についてdocsなどthis pageの承知していますC++表記を動作するPythonコードに変換することはできません。

これをPyQt-5.7のQWebEngineViewにどのように適用できますか?以下は新しいPyQtバージョンでは失敗したPyQt-5.5.1の完全な断片です:

  • ボタン1:全くマウスクリック反応がありません。
  • Button2:AttributeError: 'QWebEnginePage' object has no attribute 'mainFrame'、メインフレームを削除したとき:TypeError: toHtml(self, Callable[..., None]): not enough arguments

import sys 
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication 
from PyQt5.QtCore import QRect, Qt, QUrl, QPoint, QEvent 
from PyQt5.QtTest import QTest 
from PyQt5.Qt import PYQT_VERSION_STR

if PYQT_VERSION_STR=='5.5.1': from PyQt5 import QtWebKitWidgets else: from PyQt5 import 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_())

答えて

3

QWebEngineViewクラスは、ドロップイン置換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にアクセスするために、必要になりますWebエンジンAPIは非同期で動作し、コールバックが必要なため、いくつかの条件付きコードが必要です。また、Webエンジンのフレームを処理するためのAPIは用意されていません(JavaScriptを使用する必要があります)ので、すべてがWebページを経由する必要があります。

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) 
+0

ありがとうございます。これは完璧に動作します。 (1)QWebEngineViewの別のズームファクタ、すなわち 'self.wvTest.setZoomFactor(0.8) 'をクリックする可能性はありますか? '? (2)htmlコードを印刷するのではなく、後で処理するために文字列に保存するにはどうすればよいですか?申し訳ありませんが、私はコールバックに精通していません。 – nostradamus

+0

(1)これは、移植とは関係のない完全に別個の質問のようです。明らかにズーム係数を変更すると、入力フィールドの位置が変更されるため、それに応じて調整する必要があります。 (2)答えのサンプルコードを更新しました。 – ekhumoro

+0

どうにかして、私はそれに応じて座標を調整しましたが、(1)別の「ZoomFactor」では機能しませんでした。私は考えられるバグについて考えていましたが、もう一度それを調べなければなりません。 (2):それで、それを直接抽出する方法はありません...まあ、そうします。:)ありがとうございました。 – nostradamus