天天看點

Qt 5.5 中Qt Script翻譯 (一)

    找了半天關于QtScript的中文文檔很少,隻能檢視英文文檔,順便翻譯一下。

    Qt對基于ECMAScript的腳本提供了支援,下面的指導和參考涵蓋了ECMAScript和Qt的各個方面。

    腳本類

    下面的類将腳本的功能添加到Qt應用程式當中。

    QScriptClass                         用于定義自定義的Qt腳本對象的接口

    QScriptClassPropertyIterator        用于周遊自定義腳本對象的接口

    QScriptContext                        一個Qt腳本函數的調用上下文

    QScriptContextInfo                    關于QScriptContext的額外資訊

    QScriptEngine                        執行Qt腳本代碼的環境

    QScriptEngineAgent                    QScriptEngine執行相關事件的接口

    QScriptEngineDebugger                QScriptEngine調試環境

    QScriptProgram                        封裝了Qt腳本程式

    QScriptString                        表示QScriptEngine中字元串的句柄??

    QScriptSyntaxCheckResult            存儲腳本文法檢查的結果

    QScriptValue                        表示Qt腳本資料類型的容器

    QScriptValueIterator                QScriptValue周遊器

    QScriptable                            QtC++程式通路Qt腳本環境

    語言概述

    Qt腳本基于ECMAScript腳本語言,使用ECMA-262标準。微軟的JScript和網景的javascript也是基于ECMAScript标準,有關         ECMAScript的概述,可以檢視ECMAScript标準。如果你不熟悉ECMAScript語言,有一些指導和書籍,例如JavaScript: The       Definitive Guide.

    基本用法

    為執行腳本代碼,你可以建立一個QScriptEngine,然後調用它的evaluate()方法,傳入腳本代碼作為evaluate()的參數。

QScriptEngine engine;
    qDebug() << "the magic number is:" << engine.evaluate("1 + 2").toNumber();
           

    傳回值是evaluate()執行的結果,這個結果可以轉換為标準C++和Qt類型。

    通過設定腳本引擎的全局對象,将自定義屬性注冊到腳本引擎當中變的很容易。

engine.globalObject().setProperty("foo", 123);
    qDebug() << "foo times two is:" << engine.evaluate("foo * 2").toNumber();
           

    以上代碼是将屬性放到腳本引擎當中,這樣的腳本代碼是有效的。

    使QObject對象在QScript Engine中有效

    在腳本當中任何基于QObject執行個體是有效的。

    将QObject對象傳入QScriptEngine::newQObject()函數當中,這樣Qt腳本的封裝基于QObject的對象将會被建立,被建立的腳       本對象可以使用QObject的信号、槽、屬性、和子對象清單。

    下面是一個Qobject子類化的例子,該對象在腳本代碼中的名字是"myObject"。

QScriptEngine engine;
    QObject *someObject = new MyObject;
    QScriptValue objectValue = engine.newQObject(someObject);
    engine.globalObject().setProperty("myObject", objectValue);
           

上面的例子,在腳本環境中建立一個全局的"myObject"變量,這個變量是一個c++對象的代理。C++對象在腳本中可以用任何的名稱代指,不依賴上面的QObject::objectName().

 newQObject()函數接收兩個額外的可選參數:一個是所有權模式,另一個是可選的允許你控制QScriptValue封裝QObject的行為的容器,我們以後再回顧這些參數。

    使用信号和槽

    Qt腳本适用Qt核心的信号和槽特性,在Qt腳本當中有三種主要方式使用信号和槽。

  1.  混合C++/Script:C++應用程式代碼連接配接信号到一個腳本函數,例如,腳本函數可以使使用者打字輸入或者從檔案讀入的。如果你有一個QObject但是不想導出這個對象到腳本環境當中,隻是想腳本中定義怎樣響應

    一個信号,并且把在c++中建立連接配接。

  2. 混合Script/C++: 對于應用程式導出到腳本環境中的對象,腳本能在該對象上建立信号和槽的連接配接,在這種情況下,槽仍然寫在C++端,但是連接配接完全是腳本動态定義的。
  3. 完全腳本定義:腳本即能定義信号處理函數(相當于在Qt腳本中定義槽),也能設定這些處理程式的連接配接,例如,腳本能定義處理QLineEdit::returnPressed()信号的函數, 然後連接配接信号與這個腳本處理函數。

  用qScriptConnect()函數連接配接c++信号與腳本函數,下面的例子是定義了一個連接配接到QLineEdit::textChanged()信号的腳本處理函數:

QLineEdit *edit1 = new QLineEdit(...);
QLineEdit *edit2 = new QLineEdit(...);

QScriptValue handler = eng.evaluate("(function() { print('I am', this.name); })");
QScriptValue obj1 = eng.newObject();
obj1.setProperty("name", "the walrus");
QScriptValue obj2 = eng.newObject();
obj2.setProperty("name", "Sam");

qScriptConnect(edit1, SIGNAL(returnPressed()), obj1, handler);
qScriptConnect(edit2, SIGNAL(returnPressed()), obj2, handler);
           

       我們建立兩個QLineEdit對象并且定義一個簡單的信号處理函數,連接配接用同一個處理函數,處理函數根據不同的對象觸發

    而使用不同的this對象調用,print()代碼段的輸出将是不同的。

      在腳本代碼當中,Qt腳本用不同的句法建立和取消信号之間的連接配接,而不是像C++句法那樣隻是用QObject::connnect()。您将相關信号引用為發送器對象的屬性,并調用其connect()。有三個connect()的重載,每個都有一個相應的disconnect()過載。下面的小節描述了這三種形式。

  • 函數連接配接的是信号(信号連接配接信号)

       connect(function)

       這種連接配接情況下,connect()的參數是連接配接到信号的處理函數

function myInterestingScriptFunction() {
    // ...
}
// ...
myQObject.somethingChanged.connect(myInterestingScriptFunction);
           

    參數可以是腳本函數,例如上面的例子。也可以是一個QObject對象的slot函數,像下面的例子:

myQObject.somethingChanged.connect(myOtherQObject.doSomething);
           

    當參數是一個QObject對象的slot函數時,信号和槽的參數類型可以不相容。如果必要,Qt Script将執行信号參數的轉換,以比對時隙的參數類型。

    取消信号的連接配接,你可以調用這個信号的disconnect()函數,傳遞取消連接配接的參數: 

myQObject.somethingChanged.disconnect(myInterestingFunction);
myQObject.somethingChanged.disconnect(myOtherQObject.doSomething)
           

   當connect()隻有一個參數時,this對象将是 Global Object。

  •    信号連接配接到成員函數

    connect(thisObject, function)

    在這種連接配接方式下,第一個參數是綁定到this變量,第二個參數是被調用的函數。

    在這種方式下,如果你有一個push button,你通常想在button的點選信号觸發是做一些事情,在這種情況下,作為該對象傳遞窗體是有意義的。

var obj = { x: 123 };
var fun = function() { print(this.x); };
myQObject.somethingChanged.connect(obj, fun);
           

    取消信号的連接配接,将同樣的參數傳遞到disconnect()中:

myQObject.somethingChanged.disconnect(obj, fun);
           
  •   命名成員函數連接配接的信号

     connect(thisObject, functionName)

      在這種連接配接方式下,第一個參數是綁定到this的變量,當信号的響應函數是被調用的,第二個參數指定信号的處理函數,這種情況下涉及到處理函數是第一個參數的成員函數。    

     注意這種情況下處理函數在連接配接時已經被确定了,而不是在信号觸發是動态決定的。

var obj = { x: 123, fun: function() { print(this.x); } };
myQObject.somethingChanged.connect(obj, "fun");
           

    取消信号連接配接用同樣的參數 傳遞到disconnect() 中:

myQObject.somethingChanged.disconnect(obj, "fun");