日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

事件过滤器及不规则窗体

發布時間:2024/4/11 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 事件过滤器及不规则窗体 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

事件過濾器及不規則窗體

文章目錄

    • 事件過濾器及不規則窗體
    • 一、事件過濾器
    • 二、不規則窗體

一、事件過濾器

有時候, 對象需要查看、 甚至要攔截發送到另外對象的事件。 例如, 對話框可能
想要攔截按鍵事件, 不讓別的組件接收到; 或者要修改回車鍵的默認處理。

我們已經知道, Qt 創建了 QEvent 事件對象之后, 會調用 QObject的 event()函數處理事件的分發。 顯然, 我們可以在 event()函數中實現攔截的操作。

由于 event()函數是 protected 的, 因此, 需要繼承已有類。 如果組件很多, 就需
要重寫很多個 event()函數。 這當然相當麻煩, 更不用說重寫 event()函數還得小心
一堆問題。 好在 Qt 提供了另外一種機制來達到這一目的: 事件過濾器。

1. 事件過濾器

QObject 有一個 eventFilter()函數, 用于建立事件過濾器。 函數原型如下

virtual bool QObject::eventFilter ( QObject * watched, QEvent * event );

這個函數正如其名字顯示的那樣, 是一個“事件過濾器”。 所謂事件過濾器, 可以
理解成一種過濾代碼
事件過濾器會檢查接收到的事件。 如果這個事件是我們感興趣的類型, 就進行我們自己的處理; 如果不是, 就繼續轉發。 這個函數返回一個 bool 類型, 如果你想將參數 event 過濾出來, 比如, 不想讓它繼續轉發, 就返回 true, 否則返回 false。 事件過濾器的調用時間是目標對象(也就是參數里面的 watched 對象) 接收到事件對象之前。 也就是說, 如果你在事件過濾器中停止了某個事件, 那么, watched 對象以及以后所有的事件過濾器根本不會知道這么一個事件。

我們來看一段簡單的代碼:

class MainWindow : public QMainWindow { public:MainWindow(); protected:bool eventFilter(QObject *obj, QEvent *event); private:QTextEdit *textEdit; };MainWindow::MainWindow() {textEdit = new QTextEdit;setCentralWidget(textEdit);textEdit->installEventFilter(this); } bool MainWindow::eventFilter(QObject *obj, QEvent *event) {if (obj == textEdit) {if (event->type() == QEvent::KeyPress) {QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);qDebug() << "Ate key press" << keyEvent->key();return true;} else{return false;}} else{// pass the event on to the parent classreturn QMainWindow::eventFilter(obj, event);} }
  • MainWindow 是我們定義的一個類。 我們重寫了它的 eventFilter()函數。 為了過濾特定組件上的事件, 首先需要判斷這個對象是不是我們感興趣的組件, 然后判斷這個事件的類型。 在上面的代碼中, 我們不想讓 textEdit 組件處理鍵盤按下的事件。 所以, 首先我們找到這個組件, 如果這個事件是鍵盤事件,則直接返回true, 也就是過濾掉了這個事件, 其他事件還是要繼續處理, 所以返回 false。 對于其它的組件, 我們并不保證是不是還有過濾器, 于是最保險的辦法是調用父類的函數
  • eventFilter()函數相當于創建了過濾器, 然后我們需要安裝這個過濾器。 安裝過濾器需要調用 QObject::installEventFilter()函數。 函數的原型如下:
void QObject::installEventFilter ( QObject * filterObj )
  • 這個函數接受一個 QObject *類型的參數。 記得剛剛我們說的, eventFilter()函 數是 QObject的一個成員函數, 因此, 任意 QObject 都可以作為事件過濾器(問 題在于, 如果你沒有重寫eventFilter()函數, 這個事件過濾器是沒有任何作用 的 , 因 為 默 認 什 么 都 不 會 過 濾 ) 。 已 經存 在 的 過 濾 器 則 可 以 通 過 QObject::removeEventFilter()函數移除
  • 我 們 可 以 向 一 個 對 象 上 面 安 裝 多 個 事 件 處 理 器 , 只 要 調 用 多 次installEventFilter()函數。 如果一個對象存在多個事件過濾器, 那么, 最后一個
    安裝的會第一個執行, 也就是后進先執行的順序
bool CustomWidget::event(QEvent *e) {if (e->type() == QEvent::KeyPress) {QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);if (keyEvent->key() == Qt::Key_Tab) {qDebug() << "You press tab.";return true;}} return QWidget::event(e); }

現在, 我們可以給出一個使用事件過濾器的版本:

bool FilterObject::eventFilter(QObject *object, QEvent *event) {if (object == target && event->type() == QEvent::KeyPress){QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);if (keyEvent->key() == Qt::Key_Tab) {qDebug() << "You press tab.";return true;} else {return false;}}return false; }
  • 事件過濾器的強大之處在于, 我們可以為整個應用程序添加一個事件過濾器。 記得, installEventFilter()函數是 QObject 的函數, QApplication 或者 QCoreApplication對象都是 QObject 的子類, 因此, 我們可以向 QApplication 或QCoreApplication添加事件過濾器。 這種全局的事件過濾器將會在所有其它特性對象的事件過濾器之前調用。 盡管很強大, 但這種行為會嚴重降低整個應用程序的事件分發效率。
  • 注意,
    事件過濾器和被安裝過濾器的組件必須在同一線程, 否則, 過濾器將不起作用。
    另外, 如果在安裝過濾器之后, 這兩個組件到了不同的線程, 那么, 只有等到二者重新回到同一線程的時候過濾器才會有效

二、不規則窗體

常見的窗體是各種方形的對話框,但有時候也需要非方形的窗體,如圓形,橢圓甚至是不規則形狀的對話框。

實現步驟:

  • 新建一個項目, 比如項目名稱叫做“ShapeWidget”, 給此項目添加一個類
    “ShapeWidget”, 基類選擇“QWidget”。
  • 為了使該不規則窗體可以通過鼠標隨意拖拽, 在類中重定義鼠標事件:
    mousePressEvent()、 mouseMoveEvent()、 以及繪制函數 paintEvent()
  • “ShapeWidget”的構造函數部分是實現該不規則窗體的關鍵, 添加具體代碼如
//新建一個 Pixmap 對象 QPixmap pixmap; //加載圖片 pixmap.load(":/new/prefix1/image/sunny.png"); //固定窗口大小, 將窗口大小設置為圖片大小 setFixedSize( pixmap.width(), pixmap.height() ); //給窗口去掉邊框, 設置窗口的 flags setWindowFlags(Qt::FramelessWindowHint | windowFlags() ); //設置透明背景 setAttribute(Qt::WA_TranslucentBackground);
  • 重新實現鼠標事件和繪制函數
void ShareWidget::mousePressEvent(QMouseEvent *ev) {if(ev->button() == Qt::LeftButton){// 求出窗口移動之前的坐標m_dragPoint = ev->globalPos()-frameGeometry().topLeft();} if(ev->button() == Qt::RightButton){// 鼠標右鍵關閉窗口close();} } void ShareWidget::mouseMoveEvent(QMouseEvent *ev) {if(ev->buttons() & Qt::LeftButton){// 如果是鼠標左鍵拖動, 移動窗口move(ev->globalPos() - m_dragPoint);} } void ShareWidget::paintEvent(QPaintEvent *ev) {Q_UNUSED(ev)QPainter painter(this);// 重新繪制圖片painter.drawPixmap(0, 0, QPixmap(":/ButterFly")); }

總結

以上是生活随笔為你收集整理的事件过滤器及不规则窗体的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。