2013年6月9日 星期日

以 html5 撰寫 單機(離線)程式,以 pyside 與 qwebkit 為例。

    現在 html5 蔚為潮流,而 html5 也將觸手伸向單機程式。新的 html5 技術可以使用 ApplicationCache 來達成。而 XULRunner 又是令一個技術,讓你可以用寫網頁的方式來寫單機程式。用 pyside 加上 qwebkit 也可以達到類似的應用。事實上,pyside 加上 qwebkit 的作法不過是作個客製化瀏覽器而已。

    先看個簡單的範例。


#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys
import os.path
from PySide import QtGui, QtCore, QtWebKit


class WebviewDemo(QtGui.QWidget):

    def __init__(self):
        super(WebviewDemo, self).__init__()

        self.initUI()
        self.initEvent()
        self.initJavascriptEnv()

        self.web.page().mainFrame().javaScriptWindowObjectCleared.connect(
                self.initJavascriptEnv)

        path = os.path.dirname(__file__)
        self.web.load(QtCore.QUrl('file:///%s/demo.html' % path))

    def initUI(self):

        self.web = QtWebKit.QWebView()

        self.code_input_label = QtGui.QLabel("Code input: ")
        self.code_input = QtGui.QLineEdit()
        self.output_window = QtGui.QTextEdit()

        grid = QtGui.QGridLayout()

        grid.addWidget(self.web, 0, 0, 14, 10)
        grid.addWidget(self.code_input_label, 14, 0, 1, 1)
        grid.addWidget(self.code_input, 14, 1, 1, 9)
        grid.addWidget(self.output_window, 15, 0, 1, 10)

        self.setLayout(grid)

        self.setGeometry(300, 300, 350, 300)
        self.setWindowTitle('WebviewDemo')
        self.show()

    def initEvent(self):
        self.code_input.returnPressed.connect(self.evalJavascript)

    @QtCore.Slot(result=str)
    def evalJavascript(self):
        ''' When user input javascript code in code_input and press enter,
        it will call the function.
        '''
        code = self.code_input.text()
        page = self.web.page()
        frame = page.currentFrame()
        # run javascript code and get result.
        result =frame.evaluateJavaScript(code)
        self.output_window.append(str(result) + '\n')

    def initJavascriptEnv(self):
        page = self.web.page()
        frame = page.mainFrame()
        # Add self object into javascript runtime.
        # So the "self" object  in javascript means the "self" instance in python.
        # Note: the "self"" objeect is maybe invalid after loading new url.
        # So check
        frame.addToJavaScriptWindowObject("self", self)

    # Any function which want to be called by javascript, it need to be wrapped by QtCore.Slot.
    # If You use C++ and Qt, you also need Q_INVOKABLE macro.
    @QtCore.Slot(result=str)
    def sayHello(self):
        print 'you call python function.'
        return 'hello'

    @QtCore.Slot(result=str)
    def submit(self):
        print 'sss'
        page = self.web.page()
        frame = page.currentFrame()
        user_input = frame.findFirstElement("#fullname").evaluateJavaScript("this.value")
        QtGui.QMessageBox.warning(self, "Qt Message Box", user_input)
        return ''




def main():
    app = QtGui.QApplication(sys.argv)
    widget =  WebviewDemo()
    widget.show()

    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

    從上面範例可以看到,如果你想在 python 裡執行 javascript code 很簡單。只要簡單的呼叫 evaluateJavaScript 函數即可。然而,想要從 javascript 呼叫 python 的函數麻煩一些。首先,你要先呼叫 addToJavaScriptWindowObject 來建立一個 javascript 的物件,那個物件是對應到一個 QObject。之後你就可以用那個 javascript 來呼叫該 QObject 的 slot 方法(只有 slot 方法可以被 javascript 呼叫,一般的 function 不行)。

1 則留言:

  1. You can give around 200 slots a spin on the Slots.lv web site. The casino hosts 14 software developers, together with some of the the} greatest jackpots on the market. Super Slots’ design is exclusive and never too cluttered to slow down 먹튀검증사이트 load instances and operation. We would like to see more filtering options to make it easier to single out 3-reels, or jackpots, or anything else you wish to play.

    回覆刪除