• 《QT Creator快速入门》第六章:事件系统


    1、QEvent和事件处理

      QEvent为事件对象,其派生类有QMouseEvent、QKeyEvent、QPaintEvent、QCloseEvent、QTimterEvent等,事件可以有多种类型,如鼠标事件有鼠标按下、释放、移动等。在事件处理方法中会发出相应的信号,如下面的鼠标释放事件中会发出clicked()信号,如果设置了clicked()信号的槽方法那么就会执行它。QObject子类都可以接收和处理事件。

      void mouseReleaseEvent(QMouseEvent *e);

      处理一个事件可以有5中方法,  下面前三种事件处理动作的先后顺序是③->②->①。:

      ①、重新实现部件的paintEvent()、mousePressEvent()等事件处理方法。如果我们想要父部件也来处理子部件的事件,那么可以在子部件的事件处理方法的最后调用事件对象的ignore()方法来设置忽略该事件,那么事件就会转给父部件来处理。

      ②、重新实现QObject的event()方法,在event()方法中提前对事件进行处理:

    bool MainWindow::event(QEvent *e)
    {
        if(e->type() == QEvent::KeyPress) //键盘按下事件
            ;
        else
            ;
    
        return QMainWindow::event(e); //执行event()方法的默认操作
    }
    View Code

      ③、在对象上安装事件过滤器,调用对象的installEventFilter(QObject *)方法来安装事件过滤器,重写过滤器对象的eventFilter()方法来实现对事件的提前处理,这种方法的好处就是可以在eventFilter()方法中对多个部件的事件进行处理:

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        ui->pushButton->installEventFilter(this);
        ui->textEdit->installEventFilter(this);
        ui->spinBox->installEventFilter(this);
    }
    
    bool MainWindow::eventFilter(QObject *obj, QEvent *e)
    {
        if(obj == ui->pushButton)
        {
            if(e->type() == QEvent::MouseButtonPress)
            {
                //do something...
    
                return true; //不再传递给后面的消息处理流程
            }
            else {
                return false; //其它事件进行进一步的处理
            }
        }
        else if(obj == ui->textEdit)
        {
            if(e->type() == QEvent::Wheel)
            {
                QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(e); //转换为发生的事件类型
                if(wheelEvent->delta() > 0)
                    ui->textEdit->zoomIn();
                else
                    ui->textEdit->zoomOut();
                return true;
            }
        }
        else if(obj == ui->spinBox)
        {
            if(e->type() == QEvent::KeyPress)
            {
                QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e); //转换为发生的事件类型
                if(keyEvent->key() == Qt::Key_Space)
                {
                    ui->spinBox->setValue(0);
                    return true;
                }
            }
        }
    
        return QMainWindow::eventFilter(obj, e); //其它事件正常处理
    }
    View Code

      ④、重新实现notify方法,对象需要继承自QApplication,一般不常用。

      ⑤、在QApplication对象上安装事件过滤器,这将会使用一个全局的事件过滤器,一般不常用。

    2、QMouseEvent和QWheelEvent

      如下为对鼠标事件的一系列操作:

    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        //修改鼠标指针光标为张开的小手
        QCursor cursor; //创建光标对象
        cursor.setShape(Qt::OpenHandCursor); //设置光标形状
        setCursor(cursor); //使用光标
    }
    
    void Widget::mousePressEvent(QMouseEvent *e)
    {
        if(e->button() == Qt::LeftButton) //鼠标左键按下,修改鼠标指针光标为握住的小手
        {
            QCursor cursor;
            cursor.setShape(Qt::ClosedHandCursor);
            QApplication::setOverrideCursor(cursor); //临时改变鼠标指针光标形状
    
            m_ptOffset = e->globalPos() - pos(); //获取鼠标指针位置和当前窗口位置的差值(QPoint类型)
        }
        else { //鼠标右键按下,修改鼠标指针光标为一张图片
            QCursor cursor(QPixmap("../image.png"));
            QApplication::setOverrideCursor(cursor);
        }
    }
    
    void Widget::mouseReleaseEvent(QMouseEvent *e) //鼠标按键释放
    {
        QApplication::restoreOverrideCursor(); //恢复鼠标指针光标形状
    }
    
    void Widget::mouseMoveEvent(QMouseEvent *e) //鼠标按住左键移动的话移动当前部件
    {
        if(e->buttons() & Qt::LeftButton) //鼠标左键按下
        {
            QPoint pt = e->globalPos() - m_ptOffset; //获得新的部件位置
            move(pt); //移动部件
        }
    }
    
    void Widget::mouseDoubleClickEvent(QMouseEvent *e) //双击鼠标左键全屏或恢复原来大小
    {
        if(e->buttons() & Qt::LeftButton) //左键双击
        {
            if(windowState() != Qt::WindowFullScreen)
                setWindowState(Qt::WindowFullScreen); //设置全屏
            else
                setWindowState(Qt::WindowNoState); //恢复以前的大小
        }
    }
    
    void Widget::wheelEvent(QWheelEvent *e) //设置滚轮滑动来控制编辑器字体大小
    {
        if(e->delta() > 0) //delta获得滚轮移动的距离,滚轮旋转一下默认移动的是15,向上滚动为15,向下滚动为-15
           ui->textEdit->zoomIn(); //字体放大
        else
           ui->textEdit->zoomOut(); //字体缩小
    }
    View Code

    3、QKeyEvent

      下面是按下Ctrl + M键后最大化窗口的示例:

    void Widget::keyPressEvent(QKeyEvent* e)
    {
        if(e->modifiers() == Qt::ControlModifier) //按下了Ctrl键,Crl和Shift等需要使用modifiers()方法获取
        {
            if(e->key() == Qt::Key_M && !e->isAutoRepeat()) //按下了M键,普通按键通过key()方法获得,如果是一直按下按键的话isAutoRepeat()返回true
                setWindowState(Qt::WindowMaximized); //窗口最大化
            else if(e->key() == Qt::Key_M && e->isAutoRepeat()){
                qDebug() << "df";
            }
        }
    }
    View Code

    4、QTimerEvent

      QTimer为定时器类,以下是其使用示例:

        QTimer* timer = new QTimer(this); //创建定时器对象
        connect(timer, SIGNAL(timeout()), this, SLOT(timerOut())); //将定时器超时信号关联到当前类的timerOut方法槽上
        timer->start(1000); //开启1秒超时的定时器
    View Code

      下面是实现一个只运行一次的定时器的方法

    QTimer::singleShot(10000, this, SLOT(close())); //10秒后执行部件的close()成员方法来关闭窗口

      调用QObject的startTimer()方法也可以开启一个定时器,timerEvent()为定时事件处理方法。

     5、sendEvent()、postEvent()

      QCoreApplication的sendEvent()和postEvent()方法用来发送一个事件,sendEvent()会立即处理给定的事件,postEvent将事件投递到消息队列中,且postEvent投递的QEvent事件对象必须在堆上创建,我们不用手动释放它,因为事件队列会自动释放它。

      下面是使用sendEvent()发送向上按键按下消息到sinBox部件的示例,其中qApp为当前程序QApplication对象的全局指针:

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
        qApp->sendEvent(ui->spinBox, &keyEvent);
    }
    View Code
  • 相关阅读:
    使用docker部署zabbix
    如何用好 IDEA ,Java 撸码效率至少提升 5 倍?
    getpass模块
    linux下利用nohup后台运行jar文件包程序
    Spring Cloud 与 Dubbo 区别
    git 打标签并推送tag到托管服务器
    git-stash用法小结
    git推送本地分支到远程分支
    Git dev分支合并到master分支完美实战
    IntelliJ远程调试教程
  • 原文地址:https://www.cnblogs.com/milanleon/p/11612380.html
Copyright © 2020-2023  润新知