Qt中eventFilter()事件过滤器

eventFilter()
QObject 有一个 eventFilter() 函数,用于建立事件过滤器。这个函数的签名如下:

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

事件过滤器的原理:它会检查接收到的事件。如果这个事件是我们感兴趣的类型,就进行我们自己的处理;如果不是,就继续转发。这个函数返回一个 bool 类型,如果你想将参数 event 过滤出来,比如,不想让它继续转发,就返回 true,否则返回 false。

举例:这里使用eventFilter事件过滤器来捕获鼠标对ui中按键的一些操作,比如放在上面,离开

ui->btn_record->installEventFilter(this);
ui->pushButton_player->installEventFilter(this);
ui->pushButton_delete->installEventFilter(this);
ui->pushButton_allCheck->installEventFilter(this);
ui->tableWidget_2->viewport()->installEventFilter(this);   //注册事件过滤器

eventFilter() 函数相当于创建了过滤器,然后我们需要安装这个过滤器。上面就是给每个按键以及tablewidget都装上事件过滤器
类一定要继承于Q_OBJECT,并且在类的.h文件中说明这个函数 bool eventFilter(QObject *obj, QEvent *ev);然后在.cpp文件实现该函数

bool record::eventFilter(QObject *obj, QEvent *ev)
{
	if (obj == ui->tableWidget_2->viewport()) {
        if (ev->type() == QEvent::MouseButtonRelease)
        {
            QList<QTableWidgetItem*> items1 = ui->tableWidget_2->selectedItems();
            if(!items1.isEmpty())
            {
                int count = items1.count();//获取该行的成员数
                int row = ui->tableWidget_2->row(items1.at(0));// 获取该行的行号
                QString call_log = "record tableWidget_2 row: " + QString::number(row);
                log_filesave(call_log);
                ui->lineEdit->setText(SchNameList.at(row));
                ui->tableWidget_2->hide();
                return true;
            }
        }
    }
	
	if(obj == ui->btn_record)  //按键的事件
    {
        if(ev->type() == QEvent::HoverEnter) //鼠标放在按键上面
        {
            set_btnState(BTN_RECORD_BTN, BTN_RECORD_STATE_MOUSEOVER);
            m_recordBtnUartState = get_btnState(BTN_RECORD_BTN);
            return true;
        }
        else if(ev->type() == QEvent::HoverLeave) //鼠标离开按键
        {
            set_btnState(BTN_RECORD_BTN, m_recordBtnUartState);
            return true;
        }
    }
    return false;
}

//设置按键的状态,比如设置按键的背景
void record::set_btnState(E_BTN_RECORD_NAME buttonName, E_BTN_RECORD_STATE buttonState)
{
    switch(buttonName)
    {
        case BTN_RECORD_BTN:
            switch(buttonState)
            {
                case BTN_RECORD_STATE_NORMAL:
                    ui->btn_record->resize(NAVI_BTN_NORMAL_W, NAVI_BTN_NORMAL_H);
                    ui->btn_record->move(NAVI_BTN_NORMAL_X, NAVI_BTN_NORMAL_Y);
                    ui->btn_record->setStyleSheet("QPushButton{background-image: url(:/public/normalP/conf_menu.png);}");
                    break;
                case BTN_RECORD_STATE_MOUSEOVER:
                    ui->btn_record->resize(NAVI_BTN_NORMAL_W, NAVI_BTN_NORMAL_H);
                    ui->btn_record->move(NAVI_BTN_NORMAL_X, NAVI_BTN_NORMAL_Y);
                    ui->btn_record->setStyleSheet("QPushButton{background-image: url(:/public/mouseoverP/conf_menu.png);}");
                    break;
                case BTN_RECORD_STATE_SELECTED:
                    ui->btn_record->resize(NAVI_BTN_SELECTED_W, NAVI_BTN_SELECTED_H);
                    ui->btn_record->move(NAVI_BTN_SELECTED_X, NAVI_BTN_SELECTED_Y);
                    ui->btn_record->setStyleSheet("QPushButton{background-image: url(:/public/selectedP/conf_menu.png);}");
            }
            break;
    }
}

实际上任何子类都可以使用事件过滤器,不管是不是组件还是类

else if(obj == callnum)
    {
        if(ev->type() == QEvent::MouseButtonRelease)
        {
            QMouseEvent * e  = static_cast<QMouseEvent *>(ev);
            int mouseRelease_x = e->x();
            int mouseRelease_y = e->y();
            int currrnt_pos = 0, last_pos;

            for(int k=0;k<16;k++)   //检索呼叫列表是否有占用当前窗口
            {
                if((mouseRelease_x > (callnum->button[k]->pos().x()))  && (mouseRelease_x < ((callnum->button[k]->pos().x()) + (callnum->button[k]->size().width()))))
                {
                    if((mouseRelease_y > (callnum->button[k]->pos().y()))  && (mouseRelease_y < ((callnum->button[k]->pos().y()) + (callnum->button[k]->size().height()))))
                    {
                        for(int j=0;j<UUInfo.size();j++)
                        {
                            if(item_level3[j]->text(0) == callnum->button[k]->func_name)
                            {
                                ui->treeWidget->setCurrentItem(item_level3[j]);
                            }
                        }

                        if(CurWindow.CurSelectWindow == k)
                            return true;
                        for(int s=0;s<16;s++)
                        {
                            if(video_pos[s] == k)
                                currrnt_pos = s;
                            if(video_pos[s] == CurWindow.CurSelectWindow)
                                last_pos = s;
                        }
                        video_pos[last_pos] = k;
                        video_pos[currrnt_pos] = CurWindow.CurSelectWindow;
                        CurSelectWindowchange(last_pos);
                        return true;
                    }
                }
            }
            return true;
        }
    }

上面的例子就是一个子窗口的事件过滤器,在事件过滤器中获取鼠标点击的位置
如果事件过滤器中的事件正好是我们想要捕获的就返回true,这样事件就不会转发了,如果事件不是我们想要的,一定要返回false,否则影响其他组件,比如我们这里想要tableWidget_2和btn_record的事件,如果不返回false,每次不管哪个组件进入事件,后续都没法处理,因为事件没有了转发,其他组件无法处理事件了

eventFilter() 函数是 QObject的一个成员函数,因此,任意 QObject 都可以作为事件过滤器(问题在于,如果你没有重写eventFilter() 函数,这个事件过滤器是没有任何作用的,因为默认什么都不会过滤)。已经存在的过滤器则可以通过 QObject::removeEventFilter() 函数移除。
事件过滤器和被安装过滤器的组件必须在同一线程,否则,过滤器将不起作用。
注意,如果你在事件过滤器中 delete 了某个接收组件,务必将函数返回值设为 true。否则,Qt 还是会将事件分发给这个接收组件,从而导致程序崩溃。

只要组件注册了事件过滤器,无论任何操作都会首先进入事件过滤器,就看最后返回的true还是false,返回true不做其他处理,返回false做其他处理,

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值