我正在使用QWebview来显示由同一程序生成的html。现在,html可以引用其他资源,例如fram集中的<FRAME src=...>
。当浏览器开始下载该资源时,我必须自己拦截该请求并提供内容,因为没有涉及的网络服务器。我可以使用哪些钩子来查找请求的URL并提供生成的内容?
创建浏览器小部件:
self.browser = QWebView()
self.layout.addWidget(self.browser)
加载框架集:
self.browser.setHtml(ret.text)
现在我期望找到的是一些信号然后
self.browser.requestURI.connect(myhandler)
但我没有看到类似的东西。这里有什么更好的方法?
编辑:
主要问题似乎是使用 setHtml 。因此,似乎绕过了所有加载机制。将 load()与 QNetworkAccessManager 结合使用,效果更佳(见下文)。现在响应对象被提供给我的内容管理器,但是,我无法向响应对象写入任何内容(或实例化一个新的)。可以通过访问模式参数打开它。然后READ-ONLY错误消失,但仍然写返回-1。
我相应地重述了这个问题的标题。
from PyQt5.Qt import * # @UnusedWildImport
class ContentManager(object):
def handleRequest(self, request, response):
# response.writeData(bytearray("hello new year", "utf-8")) #THIS WORKS NOT
return response
class NAM(QNetworkAccessManager):
def __init__(self, contentManager):
super().__init__()
self.contentManager = contentManager
def createRequest(self, operation, request, device):
response = super().createRequest(operation, request, device)
return self.contentManager.handleRequest(request, response)
class Browser(QWidget):
def __init__(self):
super().__init__()
def open(self, url):
self.browser.load(QUrl(url))
def build(self, contentManager):
layout = QVBoxLayout(self)
view = QWebView()
page = view.page(); view.setPage(page)
page.setNetworkAccessManager(NAM(contentManager))
layout.addWidget(view)
self.browser = view
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Browser()
w.build(ContentManager())
w.open("index.html")
w.show()
app.exec_()
答案 0 :(得分:3)
您需要实施自定义QNetworkReply
,一般情况下,您可以随心所欲地投放任何内容{&#39;到webview(html,text,images)。
我不确定本地文件和框架,但是当您使用虚假域名时#39;必须由QNetworkAccessManager
解决它才能解决。
以下非常简单的示例使用Python 3.6.3和PyQt 5.10.0:
from PyQt5.Qt import * # @UnusedWildImport
import signal, os, sys
signal.signal(signal.SIGINT, signal.SIG_DFL)
class ContentHandler(object):
def __init__(self, url):
self.url = url
def __call__(self):
print ('ContentHandler >>', self.url)
path, basename = os.path.split(self.url)
if basename == 'index.html':
return b"hello new year", 'text/html'
class DownloadReply(QNetworkReply):
def __init__(self, parent, operation, request):
super(DownloadReply, self).__init__(parent)
self.setRequest(request)
self.setOperation(operation)
self.setUrl(request.url())
self.bytes_read = 0
self.content = b''
# give webkit time to connect to the finished and readyRead signals
QTimer.singleShot(200, self.load_content)
def load_content(self):
self.content, self.data = ContentHandler(str(self.url().toString()))()
self.offset = 0
self.open(QIODevice.ReadOnly | QIODevice.Unbuffered)
self.setHeader(QNetworkRequest.ContentTypeHeader, QVariant(self.data))
self.setHeader(QNetworkRequest.ContentLengthHeader, QVariant(len(self.content)))
self.readyRead.emit()
self.finished.emit()
def abort(self):
pass
def isSequential(self):
return True
def bytesAvailable(self):
ba = len(self.content) - self.bytes_read + super(DownloadReply, self).bytesAvailable()
return ba
def readData(self, size):
if self.bytes_read >= len(self.content):
return None
data = self.content[self.bytes_read:self.bytes_read + size]
self.bytes_read += len(data)
return data
def manager(self):
return self.parent()
class NetworkAccessManager(QNetworkAccessManager):
def __init__(self, parent=None):
super(NetworkAccessManager, self).__init__(parent=parent)
def createRequest(self, operation, request, device):
if str(request.url().host()).lower() == "myfakedom.ain":
print ('request:', request.url().host())
return DownloadReply(self, self.GetOperation, request)
return super(NetworkAccessManager, self).createRequest(operation, request, device)
if __name__ == '__main__':
app = QApplication(sys.argv)
webView = QWebView()
webView.settings().setAttribute(QWebSettings.PluginsEnabled, True)
webView.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
webView.settings().setAttribute(QWebSettings.AutoLoadImages, True)
webView.settings().setAttribute(QWebSettings.JavascriptEnabled, True)
webInspector = QWebInspector()
nam = NetworkAccessManager()
webView.page().setNetworkAccessManager(nam)
webView.load(QUrl('http://myFakeDom.ain/index.html'))
webInspector.setPage(webView.page())
window = QMainWindow()
window.setCentralWidget(webView)
window.setFixedSize(1200, 840)
window.setWindowTitle('Test')
window.show()
sys.exit(app.exec_())