WebKit WebView formunu bir Python geri aramasına bağla?


31

Küçük bir Python ve WebKit uygulaması yazıyorum; WebKit'i uygulamam için kullanıcı arayüzü olarak kullanıyorum.

Yapmak istediğim, WebKit'te etkileşimli bir öğe (yani bir açılan kutu veya tıklanabilir bölge kümesi) oluşturmak ve kullanıcı bu öğelerle etkileşime girdiğinde, biraz işlem yapmak için bir Python geri çağrısı çağırabilir ve ardından WebKit görünümünü ile güncelleyebilir. yeni bilgi.

İşte ne yapmak istediğime bir örnek:

  1. Kullanıcıya birleşik seçenekler kutusu sunulur (açılan kutu görüntülenir, sanırım, WebKit'te bir HTML formu kullanılır).
  2. Açılan kutu seçeneği seçildiğinde, on_combo_selected()Python betiğimde çağrılır ve ardından bazı veriler toplanır.
  3. Veriler WebKit'e iletilir ve görünüm güncellenir.

Bunu nasıl yapabilirim?

Yanıtlar:


31

Katıştırılmış bir WebKit widget'ından kontrol eden Python programına iletişim kurma yolları

Gtk veya Qt:

  • window.statusJavaScript'ten ayarla ; Python'da ilgili olayı yakala
  • document.titleJavaScript'ten ayarla ; Python'da ilgili olayı yakala
  • sayfayı özel bir URL’ye yeniden yönlendir (say, x-my-app:thing1/thing2/thing3); tuzak navigation-policy-decision-requestedsizin özel URL şeması ise onunla Python olay ve gittiğiniz ediliyor URL'de bakış ve anlaşma

Sadece Qt:

Teorik olarak çalışması gereken fakat pratikte yapması gereken yöntemler çok iyi değil

  • JavaScript'ten HTML öğesine (belge nesnesini dahil edecek) özel bir DOM olayı başlat; Python'daki WebKit DOM'da gezinerek ve olayları dinleyerek bu olayı Python'da yakalayın. Bu işe yarar, ancak Python’un etkinlikten özel verileri okuyabilmesini sağlamanın bir yolunu bulamıyorum, bu, işten çıkarılan olaydan başka bilgi aktaramayacağınız anlamına gelir.

Python'dan JavaScript'e iletişim kurma yolları

  • kullanın webview.execute_script(js_code). Değişken değerlerini JS ile birlikte iletiyorsanız, JSON'un kodlamaları iyi bir fikirdir; bu şekilde kaçma konusunda biraz daha az endişelenebilirsiniz ve JS yerel olarak JSON'u okuyabilir

İşte bazı örnek Gtk kodu:

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

Uzun zamandır bununla oynadım ama işte yaptığım şey:

Gibi bir şey kullanın

<form>
    <select  onchange="location.href='mycombo://'+this.value">
      <option>foo</option>
      <option>bar</option>
      <option>baz</option>
    </select>
</form>

HTML’nizde Böylece kullanıcı bir öğe mycomboseçtiğinde, seçilen değer ile -URI denir. Bunu yakalamak için bir işleyiciyi WebView'inizin navigation-requestedsinyaline bağlayın :

self.webview.connect("navigation-requested", self.on_navigation_requested)

Sinyal işleyicinizde, isteğin bir mycomboURI için olup olmadığını kontrol edersiniz . Varsa arayın 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'unuzu güncellemek için aşağıdaki execute_scriptgibi güncellemeleri yapan bazı JavaScript kodlarını çalıştırmak için işlevini kullanın:

self.webview.execute_script("document.title='Updated!';")

1
Gönderi başlıklarını nasıl alacağına dair bir fikrin var reqmı?
Flimm
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.