WebKit WebView 양식을 Python 콜백에 연결 하시겠습니까?


31

작은 Python 및 WebKit 앱을 작성 중입니다. WebKit을 앱의 UI로 사용하고 있습니다.

내가하고 싶은 일은 WebKit에서 대화 형 요소 (즉, 콤보 상자 또는 클릭 가능한 영역 집합)를 만드는 것입니다. 사용자가 이러한 요소와 상호 작용할 때 Python 콜백을 호출하여 처리를 한 다음 WebKit보기를 업데이트 할 수 있습니다 새로운 정보.

다음은 내가하고 싶은 일의 예입니다.

  1. 사용자에게는 옵션 콤보 상자가 표시됩니다 (WebKit에서 HTML 양식을 사용하여 표시되는 콤보 상자).
  2. 콤보 상자 옵션이 선택되면 on_combo_selected()파이썬 스크립트에서 호출되어 일부 데이터를 가져옵니다.
  3. 데이터가 WebKit으로 전달되고 뷰가 업데이트됩니다.

어떻게해야합니까?

답변:


31

임베디드 WebKit 위젯에서 제어 Python 프로그램으로 통신하는 방법

Gtk 또는 Qt :

  • window.statusJavaScript에서 설정 ; 파이썬에서 해당 이벤트를 트랩
  • document.titleJavaScript에서 설정 ; 파이썬에서 해당 이벤트를 트랩
  • 페이지를 맞춤 URL로 리디렉션합니다 (예 :) x-my-app:thing1/thing2/thing3. navigation-policy-decision-requested파이썬에서 이벤트를 포착 하고 탐색중인 URL을보고 사용자 정의 URL 체계 인 경우 처리하십시오.

Qt 만 :

이론적으로 작동하지만 실제로는 잘 작동하지 않는 방법

  • JavaScript에서 HTML 요소 (문서 객체를 포함 할 것)에서 사용자 정의 DOM 이벤트를 발생시킵니다. Python에서 WebKit DOM을 탐색하고 이벤트를 수신하여 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있습니까?
Flimm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.