Qt事件过滤器之eventFilter函数返回值

一、Bug描述

在编写一个ip输入的自定义控件时,对某些键盘事件进行特殊处理,编写了如下代码:

IPLineEdit.cpp
#include "iplineedit.h"
#include <QSizePolicy>
#include <QHBoxLayout>
#include <QLabel>
#include <QRegExp>
#include <QRegExpValidator>
#include <QEvent>
#include <QKeyEvent>

IPLineEdit::IPLineEdit(QWidget *parent)
    :QLineEdit(parent)
{
    QHBoxLayout *hboxLayout = new QHBoxLayout(this);
    hboxLayout->setContentsMargins(1,1,1,1);

    QRegExp regExp("(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})");

    QLabel *labelDot[3];
    for (int i=0;i<IP_INPUT_SIZE;i++) {
        m_lineEdit[i] = new QLineEdit(this);

        m_lineEdit[i]->setProperty("ip", true);

        //保存线条编辑是否使用边框绘制本身
        m_lineEdit[i]->setFrame(false);
        m_lineEdit[i]->setStyleSheet("background-color: white; color: black;");

        //输入框最大位数
        m_lineEdit[i]->setMaxLength(3);
        //消除布局中的空隙,居中
        m_lineEdit[i]->setAlignment(Qt::AlignCenter);

        //保存小部件的默认布局
        m_lineEdit[i]->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

        //添加验证规则
        m_lineEdit[i]->setValidator(new QRegExpValidator(regExp,this));

        //安装事件过滤器, 过滤子控件事件,截获控件按键,鼠标事件
        m_lineEdit[i]->installEventFilter(this);

        hboxLayout->addWidget(m_lineEdit[i]);

        if (i<3) {
            labelDot[i] = new QLabel(this);
            labelDot[i]->setText(".");
            labelDot[i]->setFixedWidth(2);
            hboxLayout->addWidget(labelDot[i]);
        }

        this->setReadOnly(true);

        m_lineEdit[0]->setFocus();
        m_lineEdit[0]->selectAll();
    }
}

IPLineEdit::~IPLineEdit()
{

}

bool IPLineEdit::eventFilter(QObject *obj, QEvent *event)
{
    if (children().contains(obj) && QEvent::KeyPress == event->type()) {

        QKeyEvent *keyEvent = dynamic_cast<QKeyEvent*>(event);
        QLineEdit *pCurrentEdit = qobject_cast<QLineEdit*>(obj);

        switch (keyEvent->key()) {
        case Qt::Key_0:
        case Qt::Key_1:
        case Qt::Key_2:
        case Qt::Key_3:
        case Qt::Key_4:
        case Qt::Key_5:
        case Qt::Key_6:
        case Qt::Key_7:
        case Qt::Key_8:
        case Qt::Key_9:
        {
            QString strText = pCurrentEdit->text();
            if (strText.length() <=3 && strText.toInt()*10 > 255) {
                int index = getIndex(pCurrentEdit);
                if (index !=-1 && index !=3) {
                    m_lineEdit[index+1]->setFocus();
                    m_lineEdit[index+1]->selectAll();
                }
            }
            return false;
            // bool b = QLineEdit::eventFilter(obj, event);
            // return QLineEdit::eventFilter(obj, event);
        }
        break;
        case Qt::Key_Left:
        {
            if (!pCurrentEdit->cursorPosition()) {
                int index = getIndex(pCurrentEdit);
                if (index != -1 && index !=0) {
                    m_lineEdit[index-1]->setFocus();
                    int length = m_lineEdit[index-1]->text().length();
                    m_lineEdit[index-1]->setCursorPosition(length?length:0);
                }
            }

            return QLineEdit::eventFilter(obj, event);
        }
        break;
        case Qt::Key_Right:
        {
            if (!pCurrentEdit->cursorPosition()) {
                int index = getIndex(pCurrentEdit);
                if (index != -1 && index !=3) {
                    m_lineEdit[index+1]->setFocus();
                    int length = m_lineEdit[index+1]->text().length();
                    m_lineEdit[index+1]->setCursorPosition(length?length:0);
                }
            }

            return QLineEdit::eventFilter(obj, event);
        }
        break;
        case Qt::Key_Backspace: //后退键
        {
            QString strText = pCurrentEdit->text();
            if (strText.isEmpty()) {
                int index = getIndex(pCurrentEdit);
                if (index != -1 && index !=0) {
                    m_lineEdit[index-1]->setFocus();
                    int length = m_lineEdit[index-1]->text().length();
                    m_lineEdit[index-1]->setCursorPosition(length?length:0);
                }
            }

            return QLineEdit::eventFilter(obj, event);
        }
        break;
        case Qt::Key_Period: //就是一个点号(.)
        {
            int index = getIndex(pCurrentEdit);
            if (index != -1 && index !=3) {
                m_lineEdit[index+1]->setFocus();
                m_lineEdit[index+1]->selectAll();
            }

            return QLineEdit::eventFilter(obj, event);
        }
        break;
        default:
            return false;
        }
    }
}

int IPLineEdit::getIndex(QLineEdit *pLineEdit)
{
    int index = -1;
    for (int i=0;i<IP_INPUT_SIZE;i++) {
        if (pLineEdit == m_lineEdit[i]) {
            index = i;
        }
    }
    return index;
}

QString IPLineEdit::text()
{
    //获取IP地址
    //192.168.1.1
    QString ip;
    for (int i=0;i<IP_INPUT_SIZE;i++) {
        ip.append(m_lineEdit[i]->text());
        if (3!=i) {
            ip.append(".");
        }
    }
    return ip;
}


IPLineEdit.h
#ifndef IPLINEEDIT_H
#define IPLINEEDIT_H

#include <QLineEdit>
#include <QWidget>

#define IP_INPUT_SIZE 4

class IPLineEdit : public QLineEdit
{
public:
    IPLineEdit(QWidget *parent =0);
    ~IPLineEdit();

    QString text();


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

private:
    QLineEdit *m_lineEdit[IP_INPUT_SIZE];
    int getIndex(QLineEdit *pLineEdit);

};

#endif // IPLINEEDIT_H

代码中将编辑框的背景设置成了黑色,但最后的运行结果却显示样式表未起作用如下图

1

二、原因分析

在Qt的事件处理系统中,eventFilter函数需要正确处理事件传递。当在eventFilter中处理特定事件后,必须决定是否将事件传递给基类或其他事件处理器。

在原始代码中,eventFilter函数在处理完特定按键事件后,没有明确返回QLineEdit::eventFilter(obj, event),这可能导致事件处理链中断。

三、解决方法

在重写的eventFilter函数最后添加返回
return QLineEdit::eventFilter(obj, event);
最后运行便能正确设置样式

2

posted @ 2025-08-13 17:29  十里八乡有名的俏佳人  阅读(12)  评论(0)    收藏  举报