小さなPythonとWebKitアプリを書いています。アプリのUIとしてWebKitを使用しています。
私がやりたいのは、WebKitでインタラクティブな要素(つまり、コンボボックスまたはクリック可能な領域のセット)を作成し、ユーザーがこれらの要素を操作するときに、Pythonコールバックを呼び出して処理を行い、次に、WebKitビューを新しい情報で更新します。
ここに私がやりたいことの例があります:
on_combo_selected()
が呼び出され、その後、いくつかのデータが取得されます。これどうやってするの?
埋め込みWebKitウィジェットから制御Pythonプログラムに通信する方法
GtkまたはQt:
window.status
を設定します。 Pythonで対応するイベントをトラップしますdocument.title
を設定します。 Pythonで対応するイベントをトラップしますx-my-app:thing1/thing2/thing3
)にリダイレクトします。 Pythonのnavigation-policy-decision-requested
イベントをトラップし、移動先のURLを確認し、カスタムURLスキームの場合はそれを処理しますQtのみ:
frame.addToJavaScriptWindowObject
を使用して(特別に設計された)PythonオブジェクトをJavaScriptグローバル名前空間に追加します。 JavaScriptからメソッドを呼び出します。 (例については http://pysnippet.blogspot.com/2010/01/calling-python-from-javascript-in-pyqts.html を参照してください。)理論的には機能するはずですが、実際には機能しない方法、非常にうまく機能します
PythonからJavaScriptへの通信方法
webview.execute_script(js_code)
を使用します。 JSで変数値を渡す場合は、JSONエンコードすることをお勧めします。そうすれば、エスケープについて少し心配する必要がなくなり、JSはJSONをネイティブに読み取ることができますGtkコードの例を次に示します。
from gi.repository import Gtk,WebKit
import json
w = Gtk.Window()
v = WebKit.WebView()
sw = Gtk.ScrolledWindow()
w.add(sw)
sw.add(v)
w.set_size_request(400,300)
w.connect("destroy", lambda q: Gtk.main_quit())
def window_title_change(v, param):
if not v.get_title():
return
if v.get_title().startswith("msgtopython:::"):
message = v.get_title().split(":::",1)[1]
# Now, send a message back to JavaScript
return_message = "You chose '%s'. How interesting." % message
v.execute_script("jscallback(%s)" % json.dumps(return_message))
v.connect("notify::title", window_title_change)
v.load_html_string("""<!doctype html>
<html>
<head>
<title>A demo</title>
<style>
body { font-family: Ubuntu, sans-serif; }
h1 { font-size: 1.3em; }
</style>
<body>
<h1>A tiny JavaScript demonstration</h1>
<form>
<p>What's your favourite thing about Jono? <select>
<option>------choose one------</option>
<option>his beard</option>
<option>his infectious sense of humour</option>
<option>his infectious diseases</option>
<option>his guitar ability</option>
<option>his wife</option>
</select></p>
</form>
<p id="out"></p>
<script>
document.querySelector("select").addEventListener("change", function() {
var chosenOption = this.options[this.selectedIndex].text;
// Now send that text back to Python by setting the title
document.title = "msgtopython:::" + chosenOption;
}, false);
function jscallback(msg) {
document.getElementById("out").innerHTML = msg;
}
</script>
</body>
</html>
""", "file:///")
w.show_all()
Gtk.main()
それで遊んでからしばらく経ちましたが、私がやったことは次のとおりです。
のようなものを使用してください
<form>
<select onchange="location.href='mycombo://'+this.value">
<option>foo</option>
<option>bar</option>
<option>baz</option>
</select>
</form>
hTMLで。したがって、ユーザーがアイテムを選択すると、選択した値を持つmycombo
- URIが呼び出されます。これをキャッチするには、WebViewのnavigation-requested
シグナルにハンドラーを接続します。
self.webview.connect("navigation-requested", self.on_navigation_requested)
シグナルハンドラで、リクエストがmycombo
URIに対するものかどうかを確認します。その場合は、on_combo_selected
を呼び出します:
def on_navigation_requested(self, view, frame, req, data=None):
uri = req.get_uri()
scheme, path=uri.split(':', 1)
if scheme == 'mycombo':
self.on_combo_selected(path)
return True
else:
return False
WebViewを更新するには、execute_script
関数を使用して、次のような更新を行うJavaScriptコードを実行します。
self.webview.execute_script("document.title='Updated!';")