1. 程式人生 > >Qt 5.5 中Qt Script翻譯 (一)

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");