将WebKit WebView表单连接到Python回调?

我正在写一个小的Python和WebKit应用程序; 我使用WebKit作为我的应用程序的UI。

我想要做的是在WebKit中创建一个交互元素(即一个combobox或一组可点击区域),当用户与这些元素交互时,我可以调用Python回调来进行一些处理,然后使用它来更新WebKit视图新的消息。

这是我想要做的一个例子:

  1. 向用户显示一个combobox选项(显示combobox,我假设,在WebKit中使用HTML表单)。
  2. 选择combobox选项后,在我的Python脚本中调用on_combo_selected() ,然后抓取一些数据。
  3. 数据传递给WebKit并更新视图。

我怎样才能做到这一点?

从嵌入式WebKit小部件到控制Python程序的通信方式

Gtk或Qt:

  • 从JavaScript设置window.status ; 在Python中捕获相应的事件
  • 从JavaScript设置document.title ; 在Python中捕获相应的事件
  • 将页面重定向到自定义URL(例如, 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 。)

理论上应该起作用但在实践中的方法不是很好

  • 从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("""   A demo   

A tiny JavaScript demonstration

What's your favourite thing about Jono?

""", "file:///") w.show_all() Gtk.main()

我玩了一段时间已经有一段时间,但这就是我的所作所为:

使用类似的东西

 

在你的HTML中。 因此,当用户选择项目时,将mycombo具有所选值的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!';")