ROOT/Signal/Slot communication
あるクラスオブジェクトの状態が変化したときにシグナルが発生し、それを受けた時に他のオブジェクトがルーチンを実行する、ということができます。
シグナルの発生
シグナルを発生させるには、RQ_OBJECT.h を include した上で、次のサンプルのようにします。
class A {
RQ_OBJECT("A")
private:
Int_t fValue;
public:
A() { fValue = 0; }
Int_t GetValue() const { return fValue; }
void SetValue(Int_t); //*SIGNAL*
};
void A::SetValue(Int_t v){
fValue = v;
Emit("SignalName(Int_t)", v);
}
まず、クラスを定義する際に、RQ_OBJECT("ClassName") という1行を追加します。そして、シグナルを発生させたいところで Emit("SignalName(Int_t)",
arg) を呼び出します。
SignalName には好きなシグナルの名前、(Int_t) の部分には引数(なんでもよい)を、arg には実際に引き渡す argument を指定します。
TCanvas には元からマウス入力やキーボード入力に対して発生する、"ProcessedEvent(Int_t event, Int_t x, Int_t y, TObject* selected)" というシグナルが用意されています。
Slot (シグナルの受け取り部)
クラス内にシグナルを受け取るための Slot として必要なのは、シグナルを受けたときに実行する関数だけです。ただし、引数にはシグナルと同じものを用意してください。
Connection
シグナルと Slot を結び付けるには、シグナル発生側のオブジェクトに対して、Connect() 関数を呼び出します。使い方は、次の通りです。
SenderObj->Connect("Signal(Int_t)", "SenderClass", RecieverObj, "Slot(Int_t)");
ここで、SenderObj はシグナル発生側のオブジェクト、"Signal(Int_t)" はシグナル名とその引数、SenderClass は RQ_OBJECT() で定義したシグナル発生クラス名、RecieverObj はシグナル受け取り側のオブジェクトポインタ、"Slot(Int_t)" はシグナルを受けて実行される関数名(Slot)です。
Connection を切るには、Disconnect()関数を呼び出します。
SenderObj->Disconnect("Signal(Int_t)", RecieverObj, "Slot(Int_t)");
Signal, RecieverObj, Slot を特に指定しないと SenderObj とつながった全ての Connection が切られます。