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的官方文档也是可以的.

    却道,此心安处是吾乡
  • 相关阅读:
    winform音频播放器(有声小说[凡人修仙传])
    c# 小小备忘录
    编程语言 : Java的动态Web解决方案泛谈
    服务器 : Apache Tomcat
    荐书 : 调试九法
    框架应用 : Spring MVC
    框架应用 : Spring
    数据库 : Mysql
    框架应用:Mybatis
    String对象的一些函数用法与心得
  • 原文地址:https://www.cnblogs.com/lucifer25/p/7812871.html
Copyright © 2011-2022 走看看