PYQT:在QThread中使用evaluatejavascript时无法访问DOM

时间:2014-01-21 16:47:29

标签: webkit pyqt qthread

我使用pyqt / webkit运行一个html文件。 我设法使用evaluateJavascript在onload回调中使用dom。 不幸的是,如果我尝试在其他地方(在Qthread内)。我无法玩DOM。请注意,评估javascript工作正常(我可以做警报)

代码如下:

index.html文件:

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>test</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
 </head>
  <body>
      <div id="info">test</div>
 </body>
</html>

和python文件:

import sys
import time
import PyQt4
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QPalette, QGraphicsScene, QGraphicsProxyWidget, QGraphicsView, QPainter
from PyQt4.QtOpenGL import QGLWidget
from PyQt4.QtCore import QObject, pyqtSlot, QUrl
from PyQt4.QtGui import QApplication
from PyQt4.QtWebKit import QWebView, QWebSettings
from PyQt4 import QtCore, QtGui, QtWebKit

global frame



class testQthread(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)


    def run(self):
        global frame
        print "****************** IN THREAD 1******************"
        time.sleep(2)   
        print frame
        frame.evaluateJavaScript(' document.getElementById("info").innerHTML="should work here";')
        while True:
           time.sleep(1)



class WithConsole(QtWebKit.QWebPage):
    def javaScriptConsoleMessage(self, msg, line, source):
        print '%s line %d: %s' % (source, line, msg)


class  HTMLApplication(object):

    def show(self):
        #It is IMPERATIVE that all forward slashes are scrubbed out, otherwise QTWebKit seems to be
        # easily confused

        #This is basically a browser instance
        self.web = QWebView()
        self.web.setAttribute(Qt.WA_X11NetWmWindowTypeDesktop)
        self.web.setAttribute(Qt.WA_OpaquePaintEvent, True)
        self.settings=self.web.settings()
        self.settings.setAttribute(QWebSettings.LocalContentCanAccessRemoteUrls, True)
        self.settings.setAttribute(QWebSettings.LocalContentCanAccessFileUrls, True)
        self.settings.setAttribute(QWebSettings.LocalStorageEnabled, True)
        self.settings.setAttribute(QWebSettings.AutoLoadImages, True)
        page = WithConsole()
        self.web.setPage(page)

        #Unlikely to matter but prefer to be waiting for callback then try to catch
        # it in time.
        self.web.loadFinished.connect(self.onLoad)

        self.web.load(QUrl("index.html"))
        self.web.show()

    def onLoad(self):
        global frame
        #This is the body of a web browser tab
        self.myPage = self.web.page()
        self.myPage.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
        self.myFrame = self.myPage.mainFrame()
        self.myFrame.evaluateJavaScript(' document.getElementById("info").innerHTML="work fine inside onLoad";')
        frame=self.myFrame




if __name__ == '__main__':
    app = QApplication(sys.argv)
    global frame

    myWebApp=HTMLApplication()
    myWebApp.show();
    d=testQthread()
    d.start()
    app.exec_()

1 个答案:

答案 0 :(得分:0)

我发现了这个问题。 pb就是gui只能由同一个线程调用。我们必须使用信号槽的东西。 好的实施应该是:

import sys
import time
import PyQt4
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QPalette, QGraphicsScene, QGraphicsProxyWidget, QGraphicsView, QPainter
from PyQt4.QtOpenGL import QGLWidget
from PyQt4.QtCore import QObject, pyqtSlot, QUrl
from PyQt4.QtGui import QApplication
from PyQt4.QtWebKit import QWebView, QWebSettings
from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyThread(QThread):
    def __init__(self, name):
        super(MyThread, self).__init__()
        self.setObjectName(name)

    def run(self):
        print "RUN", QThread.currentThread().objectName(), QApplication.instance().thread().objectName()
        self.exec_()
        print "RUN DONE", QThread.currentThread().objectName()

class Producer(QObject):
    def __init__(self, parent=None):
        super(Producer, self).__init__(parent)

    def Start(self):
        for i in range(5):
            print "Producer",i,QThread.currentThread().objectName()
            self.emit(SIGNAL("jseval"),'document.getElementById("info").innerHTML="yes I cans";')
            time.sleep(2)
        time.sleep(1)
        qApp.quit()

class Browser(QObject):
    def __init__(self, parent=None):
        super(Browser, self).__init__(parent)

    def jseval(self, val):
        self.myFrame.evaluateJavaScript(val)


    def show(self):
        self.web = QWebView()
        self.web.loadFinished.connect(self.onLoad)
        self.web.load(QUrl("index.html"))
        self.web.show()

    def onLoad(self):
        self.myPage = self.web.page()
        self.myFrame = self.myPage.mainFrame()


if __name__ == "__main__":
    app = QApplication([])
    producer = Producer()
    webBrowser = Browser()
    QThread.currentThread().setObjectName("MAIN")
    producerThread = MyThread("producer")
    producer.moveToThread(producerThread)
    producerThread.started.connect(producer.Start)
    producer.connect(producer, SIGNAL("jseval"), webBrowser.jseval)
    webBrowser.show()
    def aboutToQuit():
        producerThread.quit()
        time.sleep(1)
    qApp.aboutToQuit.connect(aboutToQuit)
    time.sleep(.1)
    producerThread.start()
    sys.exit(app.exec_())