WebKit WebViewフォームをPythonコールバックに接続しますか?


31

小さなPythonとWebKitアプリを書いています。WebKitをアプリのUIとして使用しています。

私がやりたいのは、WebKitでインタラクティブな要素(つまり、コンボボックスまたはクリック可能な領域のセット)を作成し、ユーザーがこれらの要素を操作すると、Pythonコールバックを呼び出して処理を行い、WebKitビューを更新できます新情報。

これが私がやりたいことの例です:

  1. ユーザーにはオプションのコンボボックスが表示されます(WebKitでHTMLフォームを使用すると、コンボボックスが表示されます)。
  2. コンボボックスオプションが選択さon_combo_selected()れると、Pythonスクリプトで呼び出され、いくつかのデータを取得します。
  3. データがWebKitに渡され、ビューが更新されます。

これどうやってするの?

回答:


31

組み込みWebKitウィジェットから制御Pythonプログラムと通信する方法

GtkまたはQt:

  • セットwindow.statusJavaScriptから。Pythonで対応するイベントをトラップします
  • セットdocument.titleJavaScriptから。Pythonで対応するイベントをトラップします
  • ページをカスタムURL(たとえば、x-my-app:thing1/thing2/thing3)にリダイレクトします。navigation-policy-decision-requestedPythonでイベントをトラップし、移動先のURLを確認し、カスタムURLスキームの場合はそれを処理します

Qtのみ:

理論的には機能するはずですが、実際には機能しない方法

  • JavaScriptからHTML要素(ドキュメントオブジェクトを含む)でカスタムDOMイベントを発生させます。PythonからWebKit DOMにナビゲートし、イベントをリッスンすることにより、そのイベントをPythonでトラップします。これは機能しますが、Pythonがイベントからカスタムデータを読み取れるようにする方法が見つかりません。つまり、発生したイベント以外の情報を渡すことはできません。

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()

18

それで遊んでからしばらく経ちましたが、私がやったことは次のとおりです。

のようなものを使用してください

<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)

シグナルハンドラで、リクエストがmycomboURI に対するものかどうかを確認します。もしそうなら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!';")

1
投稿ヘッダーを取得する方法はありますreqか?
フリム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.