<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                #(18):事件 事件(event)是由系統或者 Qt 本身在不同的時刻發出的。當用戶按下鼠標、敲下鍵盤,或者是窗口需要重新繪制的時候,都會發出一個相應的事件。一些事件在對用戶操作做出響應時發出,如鍵盤事件等;另一些事件則是由系統自動發出,如計時器事件。 事件也就是我們通常說的“事件驅動(event drive)”程序設計的基礎概念。事件的出現,使得程序代碼不會按照原始的線性順序執行。想想看,從最初的 C 語言開始,我們的程序就是以一種線性的順序執行代碼:這一條語句執行之后,開始執行下一條語句;這一個函數執行過后,開始執行下一個函數。這種類似“批處理”的程序設計風格顯然不適合于處理復雜的用戶交互。我們來想象一下用戶交互的情景:我們設計了一堆功能放在界面上,用戶點擊了“打開文件”,于是開始執行打開文件的操作;用戶點擊了“保存文件”,于是開始執行保存文件的操作。我們不知道用戶究竟想進行什么操作,因此也就不能預測接下來將會調用哪一個函數。如果我們設計了一個“文件另存為”的操作,如果用戶不點擊,這個操作將永遠不會被調用。這就是所謂的“事件驅動”,我們的程序的執行順序不再是線性的,而是由一個個事件驅動著程序繼續執行。沒有事件,程序將阻塞在那里,不執行任何代碼。 在 Qt 中,事件的概念似乎同信號槽類似。的確如此,一般來說,使用 Qt 組件時,我們并不會把主要精力放在事件上。因為在 Qt 中,我們關心的更多的是事件關聯的一個信號。比如,對于`QPushButton`的鼠標點擊,我們不需要關心這個鼠標點擊事件,而是關心它的`clicked()`信號的發出。這與其他的一些 GUI 框架不同:在 Swing 中,你所要關心的是`JButton`的`ActionListener`這個點擊事件。由此看出,相比于其他 GUI 框架,Qt 給了我們額外的選擇:信號槽。 但是,Qt 中的事件和信號槽卻并不是可以相互替代的。信號由具體的對象發出,然后會馬上交給由`connect()`函數連接的槽進行處理;而對于事件,Qt 使用一個事件隊列對所有發出的事件進行維護,當新的事件產生時,會被追加到事件隊列的尾部。前一個事件完成后,取出后面的事件進行處理。但是,必要的時候,Qt 的事件也可以不進入事件隊列,而是直接處理。信號一旦發出,對應的槽函數一定會被執行。但是,事件則可以使用“事件過濾器”進行過濾,對于有些事件進行額外的處理,另外的事件則不關心。總的來說,如果我們**使用**組件,我們關心的是信號槽;如果我們**自定義**組件,我們關心的是事件。因為我們可以通過事件來改變組件的默認操作。比如,如果我們要自定義一個能夠響應鼠標事件的`EventLabel`,我們就需要重寫`QLabel`的鼠標事件,做出我們希望的操作,有可能還得在恰當的時候發出一個類似按鈕的`clicked()`信號(如果我們希望讓這個`EventLabel`能夠被其它組件使用)或者其它的信號。 在前面我們也曾經簡單提到,Qt 程序需要在`main()`函數創建一個`QCoreApplication`對象,然后調用它的`exec()`函數。這個函數就是開始 Qt 的事件循環。在執行`exec()`函數之后,程序將進入事件循環來監聽應用程序的事件。當事件發生時,Qt 將創建一個事件對象。Qt 中所有事件類都繼承于`QEvent`。在事件對象創建完畢后,Qt 將這個事件對象傳遞給`QObject`的`event()`函數。`event()`函數并不直接處理事件,而是按照事件對象的類型分派給特定的事件處理函數(event handler)。關于這一點,我們會在以后的章節中詳細說明。 在所有組件的父類`QWidget`中,定義了很多事件處理的回調函數,如`keyPressEvent()`、`keyReleaseEvent()`、`mouseDoubleClickEvent()`、`mouseMoveEvent()`、`mousePressEvent()`、`mouseReleaseEvent()`等。這些函數都是 protected virtual 的,也就是說,我們可以在子類中重新實現這些函數。下面來看一個例子: ~~~ class EventLabel : public QLabel { protected: void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); }; void EventLabel::mouseMoveEvent(QMouseEvent *event) { this->setText(QString("<center><h1>Move: (%1, %2)</h1></center>") .arg(QString::number(event->x()), QString::number(event->y()))); } void EventLabel::mousePressEvent(QMouseEvent *event) { this->setText(QString("<center><h1>Press: (%1, %2)</h1></center>") .arg(QString::number(event->x()), QString::number(event->y()))); } void EventLabel::mouseReleaseEvent(QMouseEvent *event) { QString msg; msg.sprintf("<center><h1>Release: (%d, %d)</h1></center>", event->x(), event->y()); this->setText(msg); } int main(int argc, char *argv[]) { QApplication a(argc, argv); EventLabel *label = new EventLabel; label->setWindowTitle("MouseEvent Demo"); label->resize(300, 200); label->show(); return a.exec(); } ~~~ 我們編譯運行上面的代碼,就可以理解到有關事件的使用方法。 `EventLabel`繼承了`QLabel`,覆蓋了`mousePressEvent()`、`mouseMoveEvent()`和`MouseReleaseEvent()`三個函數。我們并沒有添加什么功能,只是在鼠標按下(press)、鼠標移動(move)和鼠標釋放(release)的時候,把當前鼠標的坐標值顯示在這個`Label`上面。由于`QLabel`是支持 HTML 代碼的,因此我們直接使用了 HTML 代碼來格式化文字。 `QString`的`arg()`函數可以自動替換掉`QString`中出現的占位符。其占位符以 % 開始,后面是占位符的位置,例如 %1,%2 這種。 ~~~ QString("[%1, %2]").arg(x, y); ~~~ 語句將會使用 x 替換 %1,y 替換 %2,因此,這個語句生成的`QString`為 [x, y]。 在`mouseReleaseEvent()`函數中,我們使用了另外一種`QString`的構造方法。我們使用類似 C 風格的格式化函數`sprintf()`來構造`QString`。 運行上面的代碼,當我們點擊了一下鼠標之后,label 上將顯示鼠標當前坐標值。 [![](https://box.kancloud.cn/2015-12-29_5682324abebd9.png)](http://files.devbean.net/images/2012/09/eventlabel-demo.png) 為什么要點擊鼠標之后才能在`mouseMoveEvent()`函數中顯示鼠標坐標值?這是因為`QWidget`中有一個`mouseTracking`屬性,該屬性用于設置是否追蹤鼠標。只有鼠標被追蹤時,`mouseMoveEvent()`才會發出。如果`mouseTracking`是 false(默認即是),組件在至少一次鼠標點擊之后,才能夠被追蹤,也就是能夠發出`mouseMoveEvent()`事件。如果`mouseTracking`為 true,則`mouseMoveEvent()`直接可以被發出。知道了這一點,我們就可以在`main()`函數中直接設置下: ~~~ EventLabel *label = new EventLabel; label->setWindowTitle("MouseEvent Demo"); label->resize(300, 200); label->setMouseTracking(true); label->show(); ~~~ 這樣子就沒有這個問題了。
                  <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>

                              哎呀哎呀视频在线观看