2014-01-21 3 views
0

Я запускаю html-файл, используя pyqt/webkit. Мне удается играть с dom в обратном вызове onload, используя javascript. К сожалению, если я попытаюсь сделать это в другом месте (внутри Qthread). Я не могу играть с DOM. обратите внимание, что оценка Javascript работает нормально (я могу сделать предупреждение, например)PYQT: Невозможно достичь DOM при использовании оценочного javascript в QThread

код, как показано ниже:

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> 

и файл питон:

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_() 

ответ

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_())