我正在使用PyQt应用程序,该应用程序在QWebView中使用d3显示交互式网络。当用户点击该网络中的节点时,我想将节点的ID从Javascript应用程序发送到PyQt应用程序。我试图让它与pyqtSlot装饰器一起工作,但我遇到了问题。
当我第一次将HTML加载到QWebView并公开ConnectionContainer时,我可以从Javascript成功调用Python中的change_page方法。当我尝试在click事件处理程序中调用该方法时," container",Javascript中的Python对象的名称似乎不再存在并导致错误。
如何存储此Python对象以便鼠标事件处理程序可以看到它?
Python代码:
from PyQt4.Qt import (QStandardItem, QStandardItemModel, Qt, QFont,
QWebView, pyqtSlot, QObject)
from calibre.ebooks.oeb.display.webview import load_html
class TOCView (QWebView):
def __init__(self, *args):
QWebView.__init__(self, *args)
self.container = ConnectionContainer()
self.page().mainFrame().addToJavaScriptWindowObject("container", self.container)
self.load_network()
def set_manager(self, manager):
self.container.manager = manager
def load_network(self):
path = 'C:/Users/Emily/Documents/Spring 2014/MART510 eBook Research/book_renderer.html'
load_html(path, self, codec=getattr(path, 'encoding', 'utf-8'), mime_type=getattr(path,
'mime_type', 'text/html'))
class ConnectionContainer(QObject):
def __init__(self):
QObject.__init__(self)
self.manager = None
def set_manager(self, manager):
self.manager = manager
@pyqtSlot(float)
def change_page(self, page):
print ("changed page")
if self.manager is not None:
self.manager.goto_page(page)
HTML / Javascript代码:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<style>
.link {
stroke: #666;
opacity: 0.6;
stroke-width: 1.5px;
}
.node circle {
stroke: #fff;
opacity: 0.6;
stroke-width: 1.5px;
}
text {
font: 7px serif;
opacity: 0.6;
pointer-events: none;
}
</style>
<script src=d3.v3.min.js></script>
<script>
d3.json("eBookGraph.json", dataLoaded)
function dataLoaded(data) {
var links = data.links
var nodes = data.nodes
// Compute the distinct nodes from the links.
links.forEach(function(link) {
link.source = nodes[link.source] ||
(nodes[link.source] = {name: link.source});
link.target = nodes[link.target] ||
(nodes[link.target] = {name: link.target});
link.value = +link.value;
});
var width = 500
height = 500;
var force = d3.layout.force()
.nodes(d3.values(nodes))
.links(links)
.size([width, height])
.linkDistance(50)
.charge(-200)
.on("tick", tick)
.start();
var svg = d3.select("body")
.append("svg")
.attr({
"width": "100%",
"height": "100%"
})
.attr("viewBox", "0 0 " + width + " " + height )
.attr("preserveAspectRatio", "xMidYMid meet")
.attr("pointer-events", "all")
.call(d3.behavior.zoom().on("zoom", redraw));
var vis = svg
.append('svg:g');
function redraw() {
vis.attr("transform",
"translate(" + d3.event.translate + ")"
+ " scale(" + d3.event.scale + ")");
}
var link = svg.selectAll(".link")
.data(force.links())
.enter().append("line")
.attr("class", "link")
.style("opacity", 0.4);
var node = svg.selectAll(".node")
.data(force.nodes())
.enter().append("g")
.attr("class", "node")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("click", click)
.on("dblclick", dblclick)
.call(force.drag);
node.append("circle")
.attr("r", 8)
.style("fill", "#3182bd");
node.append("text")
.attr("x", 12)
.attr("dy", ".35em")
.attr("page", function(d) { return d.id; })
.style("fill", "#000000")
.text(function(d) { return d.title; });
function tick() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}
// "change page" printed to console here
container.change_page(1.0)
function mouseover() {
}
function mouseout() {
}
function click() {
pageNum = d3.select(this).select("text").attr("page")
alert(pageNum)
// error here
container.change_page(pageNum)
alert("4")
}
function dblclick() {
}
}
</script>
</body>
答案 0 :(得分:0)
事实证明,我需要在HTML完成加载后公开容器对象。
class TOCView (QWebView):
def __init__(self, *args):
QWebView.__init__(self, *args)
self.manager = None
self.loadFinished.connect(self.load_finished)
self.load_network()
def load_finished(self):
self.page().mainFrame().addToJavaScriptWindowObject("container", self)
def set_manager(self, manager):
self.manager = manager
def load_network(self):
path = 'C:/Users/Emily/Documents/Spring 2014/MART510 eBook Research/book_renderer.html'
load_html(path, self, codec=getattr(path, 'encoding', 'utf-8'), mime_type=getattr(path,
'mime_type', 'text/html'))
@pyqtSlot(float)
def change_page(self, page):
print ("changed page: " + str(page))
if self.manager is not None:
self.manager.goto_page(page)