2009-08-19 5 views
13

Beide QWebFrame und QWebPage haben void loadFinished(bool ok) Signal, mit dem erkannt werden kann, wenn eine Webseite vollständig geladen ist. Das Problem ist, wenn eine Webseite einige Inhalte asynchron geladen hat (Ajax). Wie kann man wissen, wann die Seite in diesem Fall vollständig geladen ist?Woher weiß man, wenn eine Webseite mit QtWebKit geladen wird?

+0

Wie definieren Sie vollständig geladen? Wird eine Seite vollständig geladen, wenn gerade kein Ajax-Code läuft? (Auch wenn Ajax-Code in Zukunft ausgeführt wird?) Wird eine Seite vollständig geladen, wenn in Zukunft kein Ajax-Code mehr ausgeführt wird? Was würdest du anders machen, wenn du diese Informationen hast? (Warum spielt das eine Rolle?) – Bill

+0

In meinem Fall wird der Ajax-Aufruf beim 'onload'-Ereignis aufgerufen. Nachdem es fertig ist, denke ich an eine Seite als vollständig geladen. –

Antwort

12

Ich habe nicht wirklich das getan, aber ich denke, man kann Lage sein, Ihre Lösung zu erreichen QNetworkAccessManager verwenden.

Sie können den QNetworkAccessManager von Ihrer QWebPage mit der Funktion networkAccessManager() abrufen. QNetworkAccessManager hat ein Signal finished (QNetworkReply * reply) das ausgelöst wird, wenn eine Datei von der QWebPage-Instanz angefordert wird. Das finished Signal gibt Ihnen eine QNetworkReply-Instanz, von der Sie eine Kopie der ursprünglichen Anfrage erhalten können, um die Anfrage zu identifizieren.

So erstellen Sie einen Steckplatz zum Anhängen an das finished Signal, verwenden Sie die übergebenen Methoden von QNetworkReply, um herauszufinden, welche Datei gerade heruntergeladen hat und wenn es Ihre Ajax-Anfrage ist, tun Sie, was Sie tun müssen.

Meine einzige Einschränkung ist, dass ich das vorher noch nie gemacht habe, also bin ich mir nicht 100% sicher, dass es funktionieren würde.

Eine andere Alternative könnte sein, die Methoden von QWebFrame zu verwenden, um Objekte in das Objektmodell der Seite einzufügen und auch etwas JavaScript einzufügen, das dann Ihr Objekt benachrichtigt, wenn die Ajax-Anfrage abgeschlossen ist. Dies ist eine etwas hackere Art, es zu tun, sollte aber definitiv funktionieren.

EDIT:

Die zweite Option scheint besser zu mir. Der Arbeitsablauf lautet wie folgt:

Fügen Sie einen Slot an das QWebFrame :: javascriptWindowObjectCleared() - Signal an. Rufen Sie an dieser Stelle QWebFrame :: evaluateJavascript() auf, um Code ähnlich dem Folgenden hinzuzufügen: window.onload = function() {// Seite wurde vollständig geladen}

Geben Sie den Code ein, den Sie in dieser Funktion benötigen. Möglicherweise möchten Sie der Seite über QWebFrame :: addToJavaScriptWindowObject() ein QObject hinzufügen und dann eine Funktion für dieses Objekt aufrufen. Dieser Code wird nur ausgeführt, wenn die Seite vollständig geladen ist.

Hoffentlich beantwortet dies die Frage!

+0

Ihre Gedanken sind gut. Das mache ich jetzt und es funktioniert bis jetzt. Jetzt habe ich ein Problem, weil ich einige js Funktion anrufe, nachdem ich fertig() Signal erhalten habe und es keine Wirkung hat, obwohl es sollte. Wenn ich dieselbe js-Funktion manuell über eine Schaltfläche in einem Formular mit einer Ansicht meiner Seite aufruft, funktioniert es so, wie es sollte - es sendet einen Post, der nach zusätzlichen Daten fragt. Ich denke, warten nur auf fertig() Signal von QNAM ist nicht genug, als nach dem Empfang von Daten QWebFrame muss DOM ändern und vielleicht andere Dinge tun, bevor es bereit ist, js Anrufe zu behandeln. Bitte aktualisieren Sie Ihre Antwort, um dies zu berücksichtigen. –

+0

Können Sie mir mehr Informationen darüber geben, was genau Sie erreichen möchten? Soweit ich es verstehe, ist es dies: 1) Sie können eine Seite laden (über QWebView-> load() oder eine andere Methode) 2) Wenn der Seiteninhalt (die HTML) empfangen wurde, QNAM Brände Das fertige() Signal 3) Wenn die gesamte Seite - einschließlich JS-Dateien, CSS und Bilder - geladen wurde, löst das QWebPage-Objekt das Signal loadFinished() 4) Zu einem späteren Zeitpunkt werden zusätzliche Daten über Ajax geladen Und du willst wissen, wann # 4 passiert ist? Bitte erläutern Sie weiter und ich bin vielleicht in der Lage, Ihre Frage vollständig zu beantworten. –

+0

ad 1. Nicht genau. Ich verwende QWebFrame :: load, da ich überhaupt keine Renderingphase benötige. Momentan verwende ich ** QWebView :: setPage, um zu sehen, wie die Seite aussieht, aber dies dient nur dem Debuggen. ad 2. Ich bin nicht an HTML allein interessiert, also verwende ich dieses Signal hier nicht. ad 3. Ja. ad 4. Ja. Der Moment dieses Ajax-Aufrufs ist streng definiert; Es geschieht in dem Moment, in dem der Benutzer auf einen Teil einer Datenzeile klickt. Hier ist mein Problem. Ich rufe die gleiche js Funktion mit evaluateJavaScript auf und nichts passiert; Es wird keine Netzwerkanforderung gesendet (ich überwache alle Anfragen, die QNAM sendet). TBC –

1

Wenn Ihre ersten HTML/Bilder/etc geladen wird, das ist es. Es ist ist vollständig geladen. Diese Tatsache ändert sich nicht, wenn Sie sich dann dafür entscheiden, einige Javascript zu verwenden, um einige zusätzliche Daten, Seitenaufrufe oder was auch immer nachträglich zu erhalten.

Ich vermute, dass Sie hier ein QtScript-Objekt/Interface für Ihre Ansicht verfügbar machen möchten, das Sie über das Skript Ihrer Seite aufrufen können, um nach Ihrer Entscheidung einen "Callback" in C++ zu ermöglichen das Seitenskript), das Sie "vollständig geladen" haben.

hoffe, das hilft Ihnen eine Richtung, um zu versuchen ...

+0

Das ist nicht meine Seite, ich kann das Skript, das es enthält, nicht ändern, damit ich mein Skript/Code nicht aufrufen kann. Der Ajax-Aufruf wird ausgelöst, indem auf eine Datenzeile geklickt wird (ich programmiere diese Klicks automatisch), und ruft weitere Daten ab. Ich muss diese Daten lesen, nachdem sie geladen ist, also muss ich wissen, wann das Laden abgeschlossen ist. –

+0

Sie versuchen also, mit Qt eine Art Cross-Site-Scripting durchzuführen? Ich denke nicht, dass das funktionieren wird. Die einzige Idee, die Ihnen in den Sinn kommt, ist, dass Sie möglicherweise nach den HTTP-Status selbst suchen, die Sie nach dem geladenen Ereignis "beobachten" würden. – Shaun

+0

Warum glaubst du, dass es nicht funktioniert? Mit QtWebKit haben Sie vollen Zugriff auf DOM und JavaScript der Seite und Sie können sogar Ihr eigenes JavaScript aufrufen. Sie haben auch vollen Zugriff auf die Netzwerkebene. Was brauchst du mehr? Wofür benötigen Sie HTTP-Status? Es ist sehr Low-Level-Zeug. Alles, was ich will und brauche, ist die Möglichkeit, Benutzeraktionen in der gleichen Umgebung zu simulieren, die der Benutzer während seines normalen Browsings hat. Welche der Funktionen, die ich dafür benötige, fehlt QtWebKit aus Ihrer Sicht? –

1

Um die Belastung eines bestimmten Elements zu überprüfen, können Sie eine QTimer verwenden.So etwas wie dies in Python:

@pyqtSlot() 
def on_webView_loadFinished(self): 
    self.tObject = QTimer() 
    self.tObject.setInterval(1000) 
    self.tObject.setSingleShot(True) 
    self.tObject.timeout.connect(self.on_tObject_timeout) 
    self.tObject.start() 

@pyqtSlot() 
def on_tObject_timeout(self): 
    dElement = self.webView.page().currentFrame().documentElement() 
    element = dElement.findFirst("css selector") 
    if element.isNull(): 
     self.tObject.start() 

    else: 
     print "Page loaded" 
0

Die OP dachte, es aufgrund verzögerter AJAX-Anforderungen war, aber es könnte auch ein weiterer Grund sein, die auch erklärt, warum ein sehr kurze Zeitverzögerung das Problem behebt. Es ist ein Fehler, die das beschriebene Verhalten führt:

https://bugreports.qt-project.org/browse/QTBUG-37377

, um dieses Problem zu umgehen die loadingFinished (Signal) angeschlossen werden muss mit der Warteschlange Verbindung.

+0

Wenn ich mich richtig erinnere, war das Problem ** in meinem Fall, weil Ajax direkt nach dem Laden der Seite aufgerufen wurde. Da wir jedoch nicht wissen, was garantiert ist, bevor das 'loadFinished()' Signal ausgesendet wird, ist die einzige robuste Lösung, 'window.onload' zu verwenden, wie von Rob Knight vorgeschlagen. Wie auch immer, da die Entwicklung von QtWebKit zugunsten von QtWebEngine aufgegeben wird, würde ich nicht auf Änderungen zählen. –

+0

Ich stimme zu. Dies wird nicht mehr behoben werden. Aber der Workaround könnte immer noch nützlich sein. Ich habe meinen Beitrag bearbeitet und gesagt, dass dies ein weiterer möglicher Grund für die gegebenen Symptome ist. – Silicomancer