Qt(四)--- 事件处理机制以及QLabel的交互实现

在使用QSS给QLabel写关于pressed的属性时,发现无法实现这个属性的处理机制,然后查阅了QLabel的相关文档,发现在Qt中没有实现有关的用户交互接口,在Qt 的官方文档中,原文的内容是:
QLabelis used for displaying information in the form of text or an image.No user interaction functionality is provided. 

因此需要为QLabel自己添加事件的响应机制,比如鼠标按下等,因此需要了解一下事件的处理机制。这里有一篇博客的内容,个人觉得介绍的蛮仔细,可以借鉴的: Qt中事件处理的方法

参阅了多本有关于Qt的书籍,发现有关于Qt的事件处理机制,讲得篇幅都过于太少,过于简单,没有很好的分析处理的过程。一般来说都仅仅只是介绍了通常使用的intallEventfilter()和函数eventFilter()函数的使用,看了还是知其然还是不知其所以然,所以在这里分享一下学习时间处理机制的心得,然后给出一个关于QLabel交互实现的例子。

Qt事件

在Qt中,鼠标事件,键盘事件,定时器等事件都是以对象的形式继承自QEvent类的,完整的介绍可以参考网页:QEvent类,对于一个应用程序QApplication对象,通常会以exec()函数进入主事件处理循环并且等待,等待需要处理的事件,从事件队列里取得本地窗口系统事件,并把它们转换为QEvent并且把这些转换过的事件发给QObject。QObject通过它们的QObject::event()函数调用来接收事件。这个函数可以在子类中重新实现来处理自定义的事件和添加额外的事件类型,QWidget::event()就是一个很好的例子。默认情况下,像QObject::timerEvent()和QWidget::mouseMoveEvent()这样的事件可以被发送给事件处理函数。QObject::installEventFilter()允许一个对象中途截取发往另一个对象的事件。

事件处理机制

一般而言,在Qt中有以下五种主要的处理方法:

  1. 重新实现notify()函数。这是一个非常强大,提供了完整控制,但只能是qApp的子类。

  2. 在qApp上安装事件过滤器。这样的事件过滤器可以为所有窗口部件处理所有的事件,所以它和重新实现notify()一样强大;此外,可以有超过一个的应用程序全局事件过滤器。全局事件过滤器甚至可以看到失效的窗口部件的鼠标事件,并且如果全局鼠标跟踪生效,它可以见到所有窗口部件的鼠标移动事件。

  3. 重新实现QObject::event()(就像QWidget做的那样)。如果你这样做来得到Tab键按下,并且你会在任何窗口部件特定的事件过滤器之前看到这个事件。

  4. 在一个对象中安装事件过滤器。这样的事件过滤器可以得到除了Tab和Shift-Tab键按下之外的所有事件。

  5. 重新实现paintEvent()、mousePressEvent()和其它。这是最普通、最容易并且最不强大的方式。
划线部分是比较常用的几种方式。QLabel的pressed的事件处理的实现将会应用到这第四个处理方法。

QLabel的pressed事件的实现

因为在QLabel的基类中没有事有关于pressed事件的处理方法,因此必须以QLabel基类作为父类,对子类实现该事件处理机制,这里以搜索栏的实现,一种的搜索图标是通过QLabel实现的,以此为例进行说明:

搜索栏的ADT定义为:

#ifndef SEARCHLINE_H
#define SEARCHLINE_H

#include <QObject>
#include<QWidget>
#include<QLabel>
#include<QLineEdit>
#include<QEvent>
class searchLine : public QLineEdit
{
    Q_OBJECT
public:
    explicit searchLine(QWidget *parent=0);
    void init();
    void setLabel(const QString strPath);

signals:
    void SearchLabelClicked();
    void SearchLabelReleased();

protected:
    virtual void resizeEvent(QResizeEvent *event);
    virtual bool eventFilter(QObject *obj, QEvent *event);
private:
    QLabel *m_pSearchLabel;
};

#endif // SEARCHLINE_H
其中搜索栏的大致样式为:


对ADT的解释如下:

其中的SearchLabel就是上图的搜索图标,类似放大镜一样的图标。当点击待图标时,就会发送SearchLabelClicked的信号,释放鼠标的时候,就会发送SearchLabelReleased()的信号。

因此需要做的是,就是在对QLabel安装事件过滤器,对于事件过滤器,这里进行说明:

事件过滤器

事件过滤器是QObject成员函installEventFilter实现的,关于installEventFilter说明如下:

void QObject::installEventFilter ( const QObject * obj )

安装事件过滤器obj到这个对象。
事件过滤器就是接收所有被发送到这个对象的事件的对象。这个过滤器可以停止事件或者把它再转给这个对象。事件过滤器obj通过它的eventFilter()函数来接收

事件如果事件被过滤了(比如,停止了),eventFilter()函数必须返回真,否则它必须返回。

因此安装事件过滤器的目的是对一个或多个空间进行事件的监视,因此我们需要在QLineEdit中对QLabel进行监视,比如对鼠标事件的监视等,本文就是需要对鼠标的事件进行监视,监视鼠标点击的对象是不是QLabel以及鼠标是否释放等事件,因此相关的代码实现如下:

首先是事件过滤器的安装:

searchLine::searchLine(QWidget *parent):QLineEdit(parent)
{
    m_pSearchLabel=NULL;
    init();
}


void searchLine::init()
{
    if(m_pSearchLabel==NULL)
        m_pSearchLabel=new QLabel(this);
    this->setMinimumHeight(30);
    this->setMinimumWidth(200);

    m_pSearchLabel->installEventFilter(this);
    m_pSearchLabel->setScaledContents(false);
    m_pSearchLabel->setFixedHeight(24);
    m_pSearchLabel->setFixedWidth(24);
    m_pSearchLabel->setGeometry(5,3,24,24);
    QString strStyle=LoadStyleSheet(":/UI/searchButton.qss");
    this->setStyleSheet(strStyle);

    setTextMargins(30,0,0,0);

}
其中LoadStyleSheet的为了读取样式表的函数,实现内容如下:

QString LoadStyleSheet(const QString strPath)
{
    QFile file(strPath);
    file.open(QFile::ReadOnly);
    QString strStyle=QString::fromLatin1(file.readAll());
    return strStyle;
}

然后实现对eventFilter实现,来处理监听对象监听到的事件:

bool searchLine::eventFilter(QObject *obj, QEvent *event)
{
    if(m_pSearchLabel && obj==m_pSearchLabel)
    {
        if(event->type()==QEvent::MouseButtonPress)
        {
            QMouseEvent *mouseEvent=static_cast<QMouseEvent *>(event);
             if(mouseEvent->buttons() == Qt::LeftButton)
             {

                 emit SearchLabelClicked();
                 return true;
             }
        }
        else if(event->type()==QEvent::MouseButtonRelease)
        {
                emit SearchLabelReleased();
                return true;

        }

    }
    return QLineEdit::eventFilter(obj,event);
}

然后我们就可以对QLineEdit上的QLabel的相关信号,比如本文中的点击和释放的鼠标信号进行处理了。

你可能感兴趣的:(qt,QSS)