<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 13.2 信號與槽 信號和槽機制是 Qt 的核心機制之一,要掌握 Qt 編程就需要對信號和槽有所了解。信號和槽是一種高級接口,它們被應用于對象之間的通信,它們是 Qt 的核心特性,也是 Qt不同于其它同類工具包的重要地方之一。 在我們所了解的其它 GUI 工具包中,窗口小部件(widget)都有一個回調函數用于響應 它們觸發的動作,這個回調函數通常是一個指向某個函數的指針。在 Qt 中用信號和槽取代 了上述機制。 1\.信號(signal) 當對象的狀態發生改變時,信號被某一個對象發射( emit)。只有定義過這個信號的類或者其派生類能夠發射這個信號。當一個信號被發射時,與其相關聯的槽將被執行,就象一個正常的函數調用一樣。信號-槽機制獨立于任何 GUI 事件循環。只有當所有的槽正確返 回以后,發射函數(emit)才返回。 如果存在多個槽與某個信號相關聯,那么,當這個信號被發射時,這些槽將會一個接 一個地被執行,但是它們執行的順序將會是不確定的,并且我們不能指定它們執行的順序。 信號的聲明是在頭文件中進行的,并且 moc 工具會注意不要將信號定義在實現文件 中。Qt 用 signals 關鍵字標識信號聲明區,隨后即可聲明自己的信號。 例如,下面定義了 幾個信號: ``` signals: void yourSignal(); void yourSignal(int x); ``` 在上面的語句中,signals 是 Qt 的關鍵字。接下來的一行 void yourSignal(); 定義了信號 yourSignal,這個信號沒有攜帶參數;接下來的一行 void yourSignal(int x);定義 了信號 yourSignal(int x),但是它攜帶一個整形參數,這種情形 類似于重載。 注意,信號和槽函數的聲明一般位于頭文件中,同時在類聲明的開始位置必須加上 Q_OBJECT 語句,這條語句是不可缺少的,它將告訴編譯器在編譯之前必須先應用 moc 工具 進行擴展。關鍵字 signals 指出隨后開始信號的聲明,這里 signals 用的是復數形式而非 單數,siganls 沒有 public、private、protected 等屬性,這點不同于 slots。另外, signals、slots 關鍵字是 QT 自己定義的,不是 C++中的關鍵字。 還有,信號的聲明類似于函數的聲明而非變量的聲明,左邊要有類型,右邊要有括 號,如果要向槽中傳遞參數的話,在括號中指定每個形式參數的類型,當然,形式參數的個 數可以多于一個。 從形式上講,信號的聲明與普通的 C++函數是一樣的,但是信號沒有定義函數實現。另 外,信號的返回 類型都是 void,而 C++函數的返回值可以有豐富的類型。 注意,signal 代碼會由 moc 自動生成,moc 將其轉化為標準的 C++語句,C++預處理 器會認為自己處理的是標準 C++源文件。所以大家不要在自己的 C++實現文件實現 signal。 2\.槽(slot) 槽是普通的 C++成員函數,可以被正常調用,不同之處是它們可以與信號( signal)相 關聯。當與其關聯的信號被發射時,這個槽就會被調用。槽可以有參數,但槽的參數不能有 缺省值。 槽也和普通成員函數一樣有訪問權限。槽的訪問權限決定了誰可以和它相連。 通常, 槽也分為三種類型,即 public slots、private slots 和 protected slots。 public slots:在這個代碼區段內聲明的槽意味著任何對象都可將信號與之相連接。 這對于組件編程來說非常有用:你生成了許多對象,它們互相并不知道,把它們的信號和槽 連接起來,這樣信息就可以正確地傳遞,并且就像一個小孩子喜歡玩耍的鐵路軌道上的火車 模型,把它打開然后讓它跑起來。 protected slots:在這個代碼區段內聲明的槽意味著當前類及其子類可以將信號與之 相關聯。這些槽只是類的實現的一部分,而不是它和外界的接口。 private slots:在這個代碼區段內聲明的槽意味著只有類自己可以將信號與之相關 聯。這就是說這些槽和這個類是非常緊密的,甚至它的子類都沒有獲得連接權利這樣的信 任。 通常,我們使用 public 和 private 聲明槽是比較常見的,建議盡量不要使用 protected 關鍵字來修飾槽的屬性。此外,槽也能夠聲明為虛函數。 槽的聲明也是在頭文件中進行的。例如,下面聲明了幾個槽: ``` public slots: void yourSlot(); void yourSlot(int x); ``` 注意,關鍵字 slots 指出隨后開始槽的聲明,這里 slots 用的也是復數形式。 3\.信號與槽的關聯 槽和普通的 C++成員函數幾乎是一樣的-可以是虛函數;可以被重載;可以是共有的、 保護的或是私有的,并且也可以被其它 C++成員函數直接調用;還有,它們的參數可以是任 意類型。唯一不同的是:槽還可以和信號連接在一起,在這種情況下,每當發射這個信號的 時候,就會自動調用這個槽。 connect()語句看起來會是如下的樣子: ``` connect(sender,SIGNAL(signal),receiver,SLOT(slot)); ``` 這里的 sender 和 receiver 是指向 QObject 的指針,signal 和 slot 是不帶參數的函數 名。實際上,SIGNAL()宏和 SLOT()會把它們的參數轉換成相應的字符串。 到目前為止,在已經看到的實例中,我們已經把不同的信號和不同的槽連接在了一 起。但這里還需要考慮一些其他的可能性。 (1) 一個信號可以連接多個槽 ``` connect(slider,SIGNAL(valueChanged(int)),spinBox,SLOT(setValue(int))); connect(slider,SIGNAL(valueChanged(int)),this,SLOT(updateStatusBarIndicator(int))); ``` 在發射這個信號的時候,會以不確定的順序一個接一個的調用這些槽。 (2) 多個信號可以連接同一個槽 ``` connect() ``` 無論發射的是哪一個信號,都會調用這個槽。 (3) 一個信號可以與另外一個信號相連接 ``` connect(lineEdit,SIGNAL(textChanged(const Qstring &)),this,SIGNAL(updateRecord(const Qstring &))); ``` 當發射第一個信號時,也會發射第二個信號。除此之外,信號與信號之間的連接和信 號與槽之間的連接是難以區分的。 (4) 連接可以被移除 ``` disconnect(lcd,SIGNAL(overflow()),this,SLOT(handleMathError())); ``` 這種情況較少用到,因為當刪除對象時, Qt 會自動移除和這個對象相關的所有連接。 (5) 要把信號成功連接到槽(或者連接到另外一個信號),它們的參數必須具有相同的順序 和相同的類型 ``` connect(ftp,SIGNAL(rawCommandReply(int,const QString&)),this,SLOT(processReply(int,const QString &))); ``` (6) 如果信號的參數比它所連接的槽的參數多,那么多余的參數將會被簡單的忽略掉 ``` connect(ftp,SIGNAL(rawCommandReply(int,const Qstring &)),this,SLOT(checkErrorCode(int))); ``` 還有,如果參數類型不匹配,或者如果信號或槽不存在,則當應用程序使用調試模式 構建后,Qt 會在運行時發出警告。與之相類似的是,如果在信號和槽的名字中包含了參數 名,Qt 也會發出警告。 信號和槽機制本身是在 QObject 中實現的,并不只局限于圖形用戶界面編程中。這種 機制可以用于任何 QObject 的子類中。 當指定信號 signal 時必須使用 Qt 的宏 SIGNAL(),當指定槽函數時必須使用宏 SLOT()。如果發射者與接收者屬于同一個對象的話,那么在 connect 調用中接收者參數可 以省略。 例如,下面定義了兩個對象:標簽對象 label 和滾動條對象 scroll,并將 valueChanged()信號與標簽對象的 setNum()相關聯,另外信號還攜帶了一個整形參數,這樣標簽總是顯示滾動條所處位置的值。 ``` QLabel *label = new QLabel; QScrollBar *scroll = new QScrollBar; QObject::connect( scroll, SIGNAL(valueChanged(int)), label, SLOT(setNum(int)) ); ``` 4\.信號和槽連接示例 以下是 QObject 子類的示例: ``` class BankAccount : public QObject { Q_OBJECT public: BankAccount() { curBalance = 0; } int balance() const { return curBalance; } public slots: void setBalance(int newBalance); signals: void balanceChanged(int newBalance); private: int currentBalance; }; ``` 與多數 C++ 類的風格類似,BankAccount 類擁有構造函數、balance() “讀取”函數 和 setBalance() “設置”函數。它還擁有 balanceChanged() 信號,帳戶余額更改時將 發出此信號。發出信號時,與它相連 的槽將被執行。 Set 函數是在公共槽區中聲明的,因此它是一個槽。槽既可以作為成員函數,與其他 任何函數一樣調用,也可以與信號相連。以下是 setBalance() 槽的實現過程: ``` void BankAccount::setBalance(int newBalance) { if (newBalance != currentBalance) { currentBalance = newBalance; emit balanceChanged(currentBalance); } } ``` 語句 emit balanceChanged(currentBalance);將發出 balanceChanged() 信號,并使 用當前新余額作為其參數。 關鍵字 emit 類似于“signals”和“slots”,由 Qt 提供,并由 C++ 預處理器轉換成標準 C++ 語句。 以下示例說明如何連接兩個 BankAccount 對象: ``` BankAccount x, y; connect(&x, SIGNAL(balanceChanged(int)), &y, SLOT(setBalance(int))); x.setBalance(2450); ``` 當 x 中的余額設置為 2450 時,系統將發出 balanceChanged() 信號。y 中的 setBalance() 槽收到此信號后,將 y 中的余額設置為 2450。一個對象的信號可以與多個 不同槽相連,多個信號也可以與特定對象中的某一個槽相連。參數類型相同的信號和槽可以 互相連接。槽的參數個數可以少于信號的參數個數,這時多余的參數將被忽略。 5\.需要注意的問題 信號與槽機制是比較靈活的,但有些局限性我們必須了解,這樣在實際的使用過程中才能夠做到有的放矢,避免產生一些錯誤。下面就介紹一下這方面的情況。 (1) 信號與槽的效率是非常高的,但是同真正的回調函數比較起來,由于增加了靈活 性,因此在速度上還是有所損失,當然這種損失相對來說是比較小的,通過在一臺 i586- 133 的機器上測試是 10 微秒(運行 Linux),可見這種機制所提供的簡潔性、靈活性還是 值得的。但如果我們要追求高效率的話,比如在實時系統中就要盡可能的少用這種機制。 (2) 信號與槽機制與普通函數的調用一樣,如果使用不當的話,在程序執行時也有可能 產生死循環。因此,在定義槽函數時一定要注意避免間接形成無限循環,即在槽中再次發射 所接收到的同樣信號。 (3) 如果一個信號與多個槽相關聯的話,那么,當這個信號被發射時,與之相關的槽被 激活的順序將是隨機的,并且我們不能指定該順序。 (4) 宏定義不能用在 signal 和 slot 的參數中。 (5) 構造函數不能用在 signals 或者 slots 聲明區域內。 (6) 函數指針不能作為信號或槽的參數。 (7) 信號與槽不能有缺省參數。 (8) 信號與槽也不能攜帶模板類參數。 6\.小結 從 QObject 或其子類(例如 Qwidget)派生的類都能夠使用信號和槽機制。這種機制本身 是在 QObject 中實現的,并不只局限于圖形用戶界面編程中:當對象的狀態得到改變時, 它可以某種方式將信號發射(emit)出去,但它并不了解是誰在接收這個信號。槽被用于接收 信號,事實上槽是普通的對象成員函數。槽也并不了解是否有任何信號與自己相連接。而 且,對象并不了解具體的通信機制。這實際上是 “封裝”概念的生動體現,信號與槽機制 確保了 Qt 中的對象被當作軟件的組件來使用,體現了“軟件構件化”的思想。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看