一点一滴成长

导航

《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

 

posted on 2020-09-04 11:19  整鬼专家  阅读(340)  评论(0编辑  收藏  举报