Python 初始evaluateJavaScript()调用后出现PyQt4 QWebview错误
我有一个运行PyQt4的Python 2.7应用程序,其中有一个QWebView,它与Javascript之间有双向通信 该应用程序是通过QThreadPool、QRunnables进行多线程处理的,因此我正在使用信号与ViewController类通信 当我运行应用程序时,QWebView会加载带有外部JS和CSS的HTML。我能够通过主程序线程和ViewController类与Javascript函数交互 一旦用户选择了一个目录并且满足了某些条件,它就开始一次一个地循环执行一个不可命名的任务。在此期间,它通过信号槽调用ViewController->Javascript,正如预期的那样。问题是当我调用那些执行evaluateJavaScript的ViewController方法时,返回了一个Javascript错误 未定义的第1行:语法错误:分析错误 我反复尝试了很多错误,但似乎不明白evaluateJavaScript为什么不能在这些实例中运行。我尝试过发送简单的Javascript调用,从不接受任何参数的测试函数(认为这可能是一些奇怪的编码问题)到只发送诸如Python 初始evaluateJavaScript()调用后出现PyQt4 QWebview错误,python,qt,pyqt,pyqt4,qwebview,Python,Qt,Pyqt,Pyqt4,Qwebview,我有一个运行PyQt4的Python 2.7应用程序,其中有一个QWebView,它与Javascript之间有双向通信 该应用程序是通过QThreadPool、QRunnables进行多线程处理的,因此我正在使用信号与ViewController类通信 当我运行应用程序时,QWebView会加载带有外部JS和CSS的HTML。我能够通过主程序线程和ViewController类与Javascript函数交互 一旦用户选择了一个目录并且满足了某些条件,它就开始一次一个地循环执行一个不可命名的任务
Application.main.evaluateJavaScript(“alert('foo')”)
,它们通常在线程之外工作。我唯一能想到的另一件事是,可能需要在线程中再次调用self.main.addToJavaScriptWindowObject('view',self.view)
,但我在Application.main上运行了一个dir(),它似乎已经附加了evaluateJavaScript方法
当范围看起来是正确的,并且ViewController与QWebView的通信似乎很好时,您有没有想过为什么会发生这种情况?Qt C++中的答案可能也会起作用,如果你以前见过这种情况的话!p>
出于示例目的,我尝试简化代码:
# coding: utf8
import subprocess as sp
import os.path, os, sys, time, datetime
from os.path import basename
import glob
import random
import string
from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.QtCore import QObject, pyqtSlot, QThreadPool, QRunnable, pyqtSignal
from PyQt4.QtGui import QApplication, QFileDialog
from PyQt4.QtWebKit import QWebView
from ImportController import *
class Browser(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.resize(800,500)
self.centralwidget = QtGui.QWidget(self)
self.mainLayout = QtGui.QHBoxLayout(self.centralwidget)
self.mainLayout.setSpacing(0)
self.mainLayout.setMargin(0)
self.frame = QtGui.QFrame(self.centralwidget)
self.gridLayout = QtGui.QVBoxLayout(self.frame)
self.gridLayout.setMargin(0)
self.gridLayout.setSpacing(0)
self.html = QtWebKit.QWebView()
# for javascript errors
errors = WebPage()
self.html.setPage(errors)
self.main = self.html.page().mainFrame()
self.gridLayout.addWidget(self.html)
self.mainLayout.addWidget(self.frame)
self.setCentralWidget(self.centralwidget)
path = os.getcwd()
if self.checkNetworkAvailability() and self.checkApiAvailbility():
self.default_url = "file://"+path+"/View/mainView.html"
else:
self.default_url = "file://"+path+"/View/errorView.html"
# load the html view
self.openView()
# controller class that sends and receives to/from javascript
self.view = ViewController()
self.main.addToJavaScriptWindowObject('view', self.view)
# on gui load finish
self.html.loadFinished.connect(self.on_loadFinished)
# to javascript
def selectDirectory(self):
# This evaluates the directory we've selected to make sure it fits the criteria, then parses the XML files
pass
def evaluateDirectory(self, directory):
if not directory:
return False
if os.path.isdir(directory):
return True
else:
return False
@QtCore.pyqtSlot()
def on_loadFinished(self):
# open directory select dialog
self.selectDirectory()
def openView(self):
self.html.load(QtCore.QUrl(self.default_url))
self.html.show()
def checkNetworkAvailability(self):
#TODO: make sure we can reach the outside world before trying anything else
return True
def checkApiAvailbility(self):
#TODO: make sure the API server is alive and responding
return True
class WebPage(QtWebKit.QWebPage):
def javaScriptConsoleMessage(self, msg, line, source):
print '%s line %d: %s' % (source, line, msg)
class ViewController(QObject):
def __init__(self, parent=None):
super(ViewController, self).__init__(parent)
@pyqtSlot()
def did_load(self):
print "View Loaded."
@pyqtSlot()
def selectDirectoryDialog(self):
# FROM JAVASCRIPT: in case they need to re-open the file dialog
Application.selectDirectory()
def prepareImportView(self, displayPath):
# TO JAVASCRIPT: XML directory parsed okay, so let's show the main
Application.main.evaluateJavaScript("prepareImportView('{0}');".format(displayPath))
def generalMessageToView(self, target, message):
# TO JAVASCRIPT: Send a general message to a specific widget target
Application.main.evaluateJavaScript("receiveMessageFromController('{0}', '{1}')".format(target, message))
@pyqtSlot()
def startProductImport(self):
# FROM JAVASCRIPT: Trigger the product import loop, QThreads
print "### view.startProductImport"
position = 1
count = len(Application.data.products)
importTasks = ProductImportQueue(Application.data.products)
importTasks.start()
@pyqtSlot(str)
def updateProductView(self, data):
# TO JAVASCRIPT: Send product information to view
print "### updateProductView "
Application.main.evaluateJavaScript('updateProductView("{0}");'.format(QtCore.QString(data)) )
class WorkerSignals(QObject):
''' Declares the signals that will be broadcast to their connected view methods '''
productResult = pyqtSignal(str)
class ProductImporterTask(QRunnable):
''' This is where the import process will be fired for each loop iteration '''
def __init__(self, product):
super(ProductImporterTask, self).__init__()
self.product = product
self.count = ""
self.position = ""
self.signals = WorkerSignals()
def run(self):
print "### ProductImporterTask worker {0}/{1}".format(self.position, self.count)
# Normally we'd create a dict here, but I'm trying to just send a string for testing purposes
self.signals.productResult.emit(data)
return
class ProductImportQueue(QObject):
''' The synchronous threadpool that is going to one by one run the import threads '''
def __init__(self, products):
super(ProductImportQueue, self).__init__()
self.products = products
self.pool = QThreadPool()
self.pool.setMaxThreadCount(1)
def process_result(self, product):
return
def start(self):
''' Call the product import worker from here, and format it in a predictable way '''
count = len(self.products)
position = 1
for product in self.products:
worker = ProductImporterTask("test")
worker.signals.productResult.connect(Application.view.updateProductView, QtCore.Qt.DirectConnection)
self.pool.start(worker)
position = position + 1
self.pool.waitForDone()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
Application = Browser()
Application.raise_()
Application.show()
Application.activateWindow()
sys.exit(app.exec_())
你知道,我喜欢PyQt4,但在搜索了又搜索之后,我相信这实际上是一个bug,而不是设计的那样
此后,我继续前进,并尝试使用WxPython在CEFPython中实现这一点,对于这一特定目的,它似乎有一个更优雅的实现。你知道,我喜欢PyQt4,但在搜索和搜索之后,我相信这实际上是一个bug,而不是设计出来的 此后,我继续前进,并尝试使用WxPython在CEFPython中实现这一点,对于这一特定目的,WxPython似乎有一个更优雅的实现