【发布时间】:2019-02-05 15:55:35
【问题描述】:
我的设置就像一个在后端使用 python 并在前端使用 html/css/js 的框架。我的问题是在加载 QWebEngineView 期间出现的。
我在网上搜索了如何使用QWebEngineView建立python和javascript之间的通信,最后我尝试使用QtWebChannel。 所以我设置了一切,一切都很好地与python和javascript之间的通信,但出现了下一个问题:
- 首先:我不能直接在带有标签
<script>的html中加载javascript文件 - 第二:javascript随机加载,我尝试使用
my_view.page().runJavascript(my_js)从python加载javascript,但一次尝试两次。所以有时 jQuery 会在最后加载,所以代码的其他部分不起作用。
base.html:
<!DOCTYPE html>
<html lang="en">
<p id="log"></p>
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script>
window.onerror = function (error, url, line) {
console.error("ERROR: " + error.toString());
console.error("LINE: " + line.toString());
};
function load_app(){
new QWebChannel(qt.webChannelTransport, function (channel) {
window.app = channel.objects.app;
app.load_javascript(function(ret){
console.error("load javascript: " + ret)
});
});
}
load_app();
console.error("app loaded")
</script>
{{ application_html_content | safe }}
</html>
HTML的另一部分:
{% extends 'base.html' %}
{% block content %}
<div class="row">
{% for user_id, user in user_dict.items() %}
<div id="{{ user_id }}" class="col s12 m6">
<div class="card blue-grey darken-1">
<div class="card-content white-text">
<span class="card-title">Visit Card</span>
<p>{{ user.name }}</p>
</div>
<div class="card-action">
<button id="btn_del_{{ user_id }}" class="btn blue waves-effect waves-light" onclick="delete_user({{ user_id }})">Delete</button>
<button class="btn blue waves-effect waves-light" onclick="detail_user({{ user_id }})">Detail</button>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block javascript %}
<script>
$(document).ready(function() {
app.request_result.connect(function (result) {
if ("delete" in result) {
user_id = result.delete;
var element = document.getElementById(user_id);
element.parentNode.removeChild(element)
}
});
console.error("ready");
});
function delete_user(user_id) {
document.getElementById("btn_del_" + user_id).innerHTML = "Waiting ...";
app.request('DemoHtml:Default:delete', user_id);
}
function detail_user(user_id) {
app.path('detail_user', {"user_id": user_id});
}
</script>
{% endblock %}
load_javascript 函数:
JQUERY = "vendor/Resources/js/jquery.js"
MATERIALIZE = "vendor/Resources/css/materialize/js/materialize.js"
@pyqtSlot(result=str)
def load_javascript(self):
with open(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), self.MATERIALIZE), "r") as m_stream:
materialize_content = m_stream.read()
with open(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), self.JQUERY), "r") as j_stream:
jquery_content = j_stream.read()
self.template_view.view.page().runJavaScript(jquery_content)
self.template_view.view.page().runJavaScript(materialize_content)
return "ok"
如您所见,通常我必须在日志中看到错误:
- 首先:“加载javascript:ok”
- 第二个:“应用已加载”
但一次一二,这是相反的:
- js:应用已加载
- js: 错误: 未捕获的 ReferenceError: $ 未定义
- js:线路:67
- js: Uncaught ReferenceError: $ is not defined
- js: 加载 javascript: ok
对此有什么帮助吗?
提前感谢您!
【问题讨论】:
-
您可能需要等待脚本被执行?有一个callback function
-
runJavaScript 是异步的,所以必须等待结果才能再次调用。
-
@MauriceMeyer 所以当我的函数
load_javascript()被调用时,我可以在runJavascript()中设置回调来强制加载等待结束的页面? @ekhumoro 我如何等待结果?runJavaScript()只需加载 jQuery -
@FlorianCouderc 如链接文档中所述,传递给
runJavascript的回调将在返回时被调用。所以只需将runJavascript调用链接在一起,而不是一个接一个地调用它们。您还可以创建一个带有本地事件循环的包装函数,该函数在调用回调之前一直阻塞。这将有效地制作runJavascript的同步版本。
标签: javascript python-3.x pyqt5 qtwebengine