zoukankan      html  css  js  c++  java
  • chapter7 事件处理

    chapter7 事件处理

    事件(event)是由窗口系统或者Qt自身产生的,用以响应所发生的各类事情.我们在前面已经接触到,在main.cpp的结尾处,我们用:

    app.exec();

    表示进入应用程序的循环,应用程序会监听各类事件,然后予以相应.

    这里我们要区分"事件"和"信号",相较而言,"事件"属于更为底层的触发机制,"信号"可以说是"事件"的一个结果,在使用窗口部件的时候,我们通常是和"信号"打交道,但如果涉及到具体的实现,就要去寻找相应的"事件"了.举个例子:QPushButton有clicked()信号,这个信号的发出,正是由于触发了鼠标的QMouseEvent事件才被emit出来.

    在Qt中,事件就是QEvent的子类,子类的类型有很多,可以用QEvent::type()返回枚举值.不过我们通常接触到的,有QMousEvent, QKeyEvent, QPaintEvent等,我们通常可以重写这些事件内部的代码,来实现我们期待的功能.

    ticker.h

    #ifndef TICKER_H
    #define TICKER_H
    
    #include <QWidget>
    
    namespace Ui {
    class Ticker;
    }
    
    class Ticker : public QWidget
    {
        Q_OBJECT
        Q_PROPERTY(QString text READ text WRITE setText)
    
    public:
        explicit Ticker(QWidget *parent = 0);
    
        void setText(const QString &newText);
        QString text() const { return myText; }
        QSize sizeHint() const;
        ~Ticker();
    protected:
        void paintEvent(QPaintEvent *event);
        void timerEvent(QTimerEvent *event);
        void showEvent(QShowEvent *event);
        void hideEvent(QHideEvent *event);
    private:
        Ui::Ticker *ui;
        QString myText;
        int offset;
        int myTimerId;
    };
    
    #endif // TICKER_H
    

    可以看出,各类事件基本都是protected的,这里我们重写窗口绘制事件,还有一个定时器时间,一个窗口显示,隐藏事件.

    1.重新实现事件处理器

    ticker.cpp

    #include "ticker.h"
    #include "ui_ticker.h"
    #include <QPainter>
    
    Ticker::Ticker(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Ticker)
    {
        ui->setupUi(this);
        offset = 0;
        myTimerId = 0;
    }
    
    Ticker::~Ticker()
    {
        delete ui;
    }
    
    void Ticker::setText(const QString &newText){
        myText = newText;
        update();
        updateGeometry();
    }
    
    QSize Ticker::sizeHint() const{
        return fontMetrics().size(0, text());
    }
    
    void Ticker::paintEvent(QPaintEvent *event){
        QPainter painter(this);
    
        int textWidth = fontMetrics().width(text());
        if(textWidth < 1){
            return;
        }
        int x = -offset;
        while(x < width()){
            painter.drawText(x, 0, textWidth, height(),
                             Qt::AlignLeft | Qt::AlignVCenter, text());
            x += textWidth;
        }
    }
    
    void Ticker::showEvent(QShowEvent *event){
        myTimerId = startTimer(30);
    }
    
    void Ticker::timerEvent(QTimerEvent *event){
        if(event->timerId() == myTimerId){
            ++offset;
            if(offset >= fontMetrics().width(text())){
                offset = 0;
            }
            scroll(-1, 0);
        }else{
            QWidget::timerEvent(event);
        }
    }
    
    void Ticker::hideEvent(QHideEvent *event){
        killTimer(myTimerId);
        myTimerId = 0;
    }
    

    在调用update()和scroll()的时候,都会触发paintEvent()重新绘制窗体,startTimer(30)是每隔30毫秒,就会发射一个定时器事件,然后用timerEvent()事件来捕捉.

    2.事件的传递

    事件是作用于具体的对象,但是事件从触发,到进入该对象内部的处理事件函数时,经历了以下几个过程:

    父对象的eventFilter()->窗体部件的event()->窗体部件的更具体的事件,如keyPressEvent()->父对象的keyPressEvent()

    是有一个传递的过程的,在各个部分,事件都可以选择拦截.比如在窗体部件的keyPressEvent()事件中,如果选择accept(),则事件不会传递给父窗体,而如果选择ignore(),事件就会上浮,被父窗体捕获,引起触发.

    还有一个更强的方式,就是为子窗体安装事件过滤器installEvent(),这样事件在到达子窗体之前,会先经过父窗体的eventFilter()事件过滤器,事件过滤器可以自由的编写,判断事件触发的对象,以及触发的类型,可以选择拦截,也可以选择忽略,直接调用父类的eventFiler()函数,执行默认的一些操作,这点而言,是非常重要的.

    总结:应该说事件系统是Qt中很重要的部分,但是基本的一些思路,不是很难掌握,当然事件处理中还是有一些比较高级的用法的,很复杂,但是多数情况下并不会用到,因此在需要的时候,再去查看Qt的官方文档也是可以的.

    却道,此心安处是吾乡
  • 相关阅读:
    Lucene in action 笔记 case study
    关于Restful Web Service的一些理解
    Lucene in action 笔记 analysis篇
    Lucene in action 笔记 index篇
    Lucene in action 笔记 term vector
    Lucene in action 笔记 search篇
    博客园开博记录
    数论(算法概述)
    DIV, IFRAME, Select, Span标签入门
    记一个较困难的SharePoint性能问题的分析和解决
  • 原文地址:https://www.cnblogs.com/lucifer25/p/7812871.html
Copyright © 2011-2022 走看看