2020年9月29日 星期二

特製 Widget 的滑鼠事件

特製 Widget 的滑鼠事件

前言

  在先前的 特製 Widget 裡特製了 Widget ,這次來學習如何在特製的 Widget 裡處理滑鼠事件,在此做個紀錄。

內容

    先到 [ GitLab ] HelloQt 下載範例,這次應用的專案路徑
(HelloQt' directory)/Widget/MouseEvent,ouseEvent,執行結果如下
範例的執行結果

在 Widget 上做出點擊可以看到偵錯訊息。

  由於這次的範例是依據 特製 Widget 的範例改造而來,所以不會說明如何特製一個 Widget 。特製的 Widget 是如何處理滑鼠事件呢?透過 Qt 常見的綁定事件嗎?還記得特製 Widget 時事透過繼承 QWidget 這個類別嗎?這個類別提供滑鼠事件的 Virtual function 介面,只需要做覆寫(override)的動作就可以處理滑鼠的相關事件。接著看到宣告的部分,程式碼如下
#include <QWidget>

#include <QPainter>
#include <QMouseEvent>
#include <QWheelEvent>
class MyWidget : public QWidget
{
  Q_OBJECT
public:
  explicit MyWidget(QWidget *parent = nullptr);
protected:
  void paintEvent(QPaintEvent *event) override;
  void mouseDoubleClickEvent(QMouseEvent *event) override;
  void mouseMoveEvent(QMouseEvent *event) override;
  void mousePressEvent(QMouseEvent *event) override;
  void mouseReleaseEvent(QMouseEvent *event) override;
  void wheelEvent(QWheelEvent *event) override;
signals:

};

滑鼠的事件介面分別為 mouseDoubleClickEvent() 、 mouseMoveEvent() 、MousePressEvent() 、mouseReleaseEvent() 與 WheelEvent() ,  mouseDoubleClickEvent() 處理雙擊事件,但要注意的是發生雙擊之前必定會發生單擊事件, mouseMoveEvent() 處理的是壓住某個按鍵後拖動的事件,MousePressEvent() 處理單擊事件, mouseReleaseEvent() 處理按鍵放開, WheelEvent() 處理耍的滾輪,由於事件處理需要用到 QMouseEvent 與 QWheelEvent ,所以記得要 include 相關檔案。看到實作的程式碼如下
void MyWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
  qDebug( "mouseDoubleClickEvent" );
}

void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
  qDebug( "mouseMoveEvent" );
}

void MyWidget::mousePressEvent(QMouseEvent *event)
{
  qDebug( "mousePressEvent" );
  //
  switch( event->button() )
  {
  case Qt::LeftButton:
    qDebug( "Left button clicked" );
    break;
  case Qt::MidButton:
    qDebug( "Middle button clicked" );
    break;
  case Qt::RightButton:
    qDebug( "Right button clicked" );
    break;
  default:
    qDebug( "Unknown button clicked" );
    break;
  }
  //
  qDebug( "PoxX:%ld PosY:%ld" ,event->x() , event->y() );
}

void MyWidget::mouseReleaseEvent(QMouseEvent *event)
{
  qDebug( "mouseReleaseEvent" );
}

void MyWidget::wheelEvent(QWheelEvent *event)
{
  qDebug( "wheelEvent" );
  qDebug( "wheel:%ld" , event->delta() );

}

滑鼠的事件都會把詳細資訊記錄在 QMouseEvent 裡,如是滑鼠左鍵或滑鼠右鍵來觸發該事件,看到 MousePressEvent() ,可以透過 QMouseEvent::button() 來取得是哪個按鍵來處理,並可透過 QMouseEvent::x() 與 QMouseEvent::y() 來取得觸發事件的位置, mouseDoubleClickEvent() 、 mouseMoveEvent()  與 mouseReleaseEvent() 處理方法類似所以就只單純顯示偵錯訊息來知道觸發事件的時機。滑鼠滾輪的事件會把詳細資訊記錄在 QWheelEvent 裡,可以透過 QWheelEvent::delta() 來取得上滾或下滾的數值,這個數值基本上都是以 120 為單位,上跟下滾是用數值的正負來表達。

  最後來說一下滾輪事件的奇怪現象,在範例看到的數值不是 120 就是 -120 ,但我在另一個比較複雜的專案使用同樣的方法來取得滾輪數值時可以看到 240 或 360 之類的數值,也許你會很直覺的認定這是滾輪速度的差別,但經我實驗發現同樣的滾動在本範例會送多次的 wheelEvent()
,數值都是 120 ,但在複雜的範例卻發動少次 wheelEvent() ,但有些數值是 240 或 360  ,所以就這實驗來看,其實看到大於 120 數值所代表的是 Qt 的事件觸發時機比較慢所造成滾輪數值會比較大。

沒有留言:

張貼留言