Qt中,事件作为一个对象,继承自QEvent类,常见的有键盘事件QKeyEvent、鼠标事件QMouseEvent和定时器事件QTimerEvent等。Qt中,任何QObject子类示例都可以接收和处理事件。实际编程中通常实现部件的paintEvent()、mousePressEvent()等事件处理函数来处理特定部件的特定事件。
每个程序的main函数最后都会调用QApplication类的exec()函数,它会使Qt应用程序进入到事件循环,使应用程序在运行的时候接收各种事件。一旦有事件发生,Qt便会构造一个相应的QEvent子类的对象来表示它,然后将它传递给QObject对象或子对象。
鼠标事件
将鼠标移动、按下与释放时的位置希纳是在状态栏中。
在构造函数中。向状态栏添加两个永久QLabel标签,m_statusLabel用来信息提示,m_sposLabel用来显示鼠标移动时的坐标
setWindowTitle("鼠标事件");
m_statusLabel = new QLabel(QString("当前位置:"));
m_statusLabel->setFixedWidth(100);
m_posLabel = new QLabel("");
m_statusLabel->setFixedWidth(100);
//状态栏添加永久标签
statusBar()->addPermanentWidget(m_statusLabel);
statusBar()->addPermanentWidget(m_posLabel);
重写鼠标按下方法:
void MouseEvent::mousePressEvent(QMouseEvent *event){//拼接字符串(34,45)QString str="("+QString::number(event->x())+","+QString::number(event->y())+")";//判断是否左键按下if(event->button()==Qt::LeftButton){statusBar()->showMessage(QString("左键:")+str);}else if(event->button()==Qt::MidButton){statusBar()->showMessage(QString("中键:")+str);}else if(event->button()==Qt::RightButton){statusBar()->showMessage(QString("右键:")+str);}
}
重写鼠标移动方法:
void MouseEvent::mouseMoveEvent(QMouseEvent *event){//字符串拼接(45,32)QString str = "("+QString::number(event->x())+","+QString::number(event->y())+")";m_posLabel->setText(str);
}
重写鼠标松开方法:
void MouseEvent::mouseReleaseEvent(QMouseEvent *event){//字符串拼接(45,23)QString str="("+QString::number(event->x())+","+QString::number(event->y())+")";//消息显示3sstatusBar()->showMessage(QString("释放在:")+str,3000);
}
键盘事件
当按方向键时,图片每次移动20像素;当按下Ctrl+方向键时,图片每次移动1像素
新建桌面应用程序testKeyEvent,类名KeyEvent,基类QWidget,通过重写键盘事件到达操作的键盘的时候窗口中的图片上下左右移动,类似QtCreator设计模式下通过按键摆放部件时的效果。
将网格线和图片绘制在一个QPixmap类上,每次有上下左右按键时重新绘制QPixmap。重写绘制方法,将图片绘制到应用程序上。
将网格线与图片绘制到QPixmap类上,m_pix是一个和应用程序一样大小的QPixmap类:
void KeyEvent::drawPix(){m_pix->fill(Qt::white);QPainter painter(this);QPen pen(Qt::DotLine);//设置画笔样式点线样式painter.begin(m_pix);//指定m_pix为绘图设备painter.setPen(pen);//给背景画虚线//按照步长画纵向网格线for(int i=m_step;i<m_width;i+=m_step){painter.drawLine(QPoint(i,0),QPoint(i,m_height));//画线}for(int i=m_step;i<m_height;i+=m_step){painter.drawLine(QPoint(0,i),QPoint(m_width,i));//画线}painter.end();//画图片painter.begin(m_pix);painter.drawImage(QPoint(m_startX,m_starty),m_image);painter.end();
}
重写绘制方法,将QPixmap类绘制到应用程序上:
void KeyEvent::paintEvent(QPaintEvent *event){QPainter painter;painter.begin(this);painter.drawPixmap(QPoint(0,0),*m_pix);painter.end();
}
重写按键方法,判断按键类型,如果是Ctrl+方向键则每次移动距离一个像素,如果仅是方向键则每次移动20像素:
m_startx和m_starty为int类型,用来记录QPixmap类上图片的位置;m_height和m_width也为int类型,用来记录应用程序的高、宽。
程序直接结束后调用update( )方法重绘应用程序。
void KeyEvent::keyPressEvent(QKeyEvent *event){//按下Ctrl键if(event->modifiers()==Qt::ControlModifier){if(event->key()==Qt::Key_Left){m_startX= (m_startX-1)>0 ? m_startX-1 : m_startX;}else if(event->key()==Qt::Key_Right){m_startX = (m_startX+1+m_image.width())>m_width ?m_startX:m_startX+1;}else if(event->key()==Qt::Key_Up){m_starty = (m_starty-1) >0 ?m_starty-1:m_starty;}else if(event->key()==Qt::Key_Down){m_starty = (m_starty+1+m_image.height()) <m_height ?m_starty+1:m_starty;}}else{//图标左上角移动到网格顶点上m_startX = m_startX - (m_startX%m_step);m_starty = m_starty - (m_starty%m_step);if(event->key()==Qt::Key_Left){m_startX= (m_startX-m_step)>0 ? m_startX-m_step : m_startX;}else if(event->key()==Qt::Key_Right){m_startX = (m_startX+m_step+m_image.width())>m_width ?m_startX:m_startX+m_step;}else if(event->key()==Qt::Key_Up){m_starty = (m_starty-m_step) >0 ?m_starty-m_step:m_starty;}else if(event->key()==Qt::Key_Down){m_starty = (m_starty+m_step+m_image.height()) <m_height ?m_starty+m_step:m_starty;}}//重绘drawPix();update();//触发窗口重绘
}
构造函数:
setWindowTitle("键盘事件");
setAutoFillBackground(true);//背景自动填充
setFixedSize(512,256);
m_width=size().width();
m_height=size().height();m_pix=new QPixmap(m_width,m_height);
m_pix->fill(Qt::white);//填充颜色
m_image.load("tiger.png");
m_startX=100;
m_starty=100;
m_step=20 ;drawPix();
事件过滤
void QObject::installEventFilter(QObject *filterObj)
bool eventFilter(QObject *obj, QEvent *event);
Qt的事件过滤由以上两个方法实现,首先对需要监听的对象安装一个事件过滤器,调用installEventFilter( )方法,参数filterObj表示监听者,它监听发送到此对象的所有事件。过滤器可以停止此事件,也可以iang此事件发送给此QObject对象那个。世家过滤器filterObj用过它的eventFilter( )函数接收事件。
重写bool eventFilter(QObject *obj, QEvent *event)方法用来对过滤的事件进行处理
eventFilter()的返回值。
如果返回true,表示事件过滤,不会发送到对象本身。
如果返回false,表示事件未过滤,会通过event()方法将事件分发到对象。
返回给基类进行处理,例:return QObject::eventFilter(obj, event)。
示例
鼠标左键、中键和右键点击图片时图片放大,松开时图片回到原始大小。同时,将对应的鼠标事件的信息显示在右边标签内,
构造函数中初始化部件,并将图片所在的标签部件安装事件过滤器
setWindowTitle("事件过滤");//设置标题
m_stateLabel=new QLabel("鼠标按下标志");//显示鼠标事件信息
m_image.load("fly3.png");//加载图片
m_label=new QLabel;
m_label->setPixmap(QPixmap::fromImage(m_image));//将图片添加到标签中
//将标签添加到水平布局管理器中
QHBoxLayout *layout=new QHBoxLayout;
layout->addWidget(m_label);
layout->addWidget(m_stateLabel);
resize(m_image.width()*2,m_image.height());//设置窗体大小//给图片标签安装事件过滤,指定整个窗体为监视事件的对象
m_label->installEventFilter(this);setLayout(layout);//设置应用程序的布局管理器
redStyle="QLabel{color:red;font:24px}";
greenStyle="QLabel{color:green;font:24px}";
blueStyle="QLabel{color:blue;font:24px}";
重写bool eventFilter(QObject *watched, QEvent *event)
bool eventFilter(QObject *watched, QEvent *event){QMatrix matrix;//用于指定坐标系的2D变化QImage tmpImg; //保存处理后的图片//放大图片matrix.scale(1.3,1.3);//判断是否是图片标签if(watched==m_label){//判断事件是否为鼠标事件if(event->type()==QEvent::MouseButtonPress){//将事件强转为鼠标事件QMouseEvent *mouseEvent=(QMouseEvent*)event;//判断鼠标事件类型if(mouseEvent->buttons()&Qt::LeftButton){m_stateLabel->setText("左键按下中间图片");m_stateLabel->setStyleSheet(redStyle);}else if(mouseEvent->buttons()&Qt::MidButton){m_stateLabel->setText("中键按下中间图片");m_stateLabel->setStyleSheet(greenStyle);}else if(mouseEvent->buttons()&Qt::RightButton){m_stateLabel->setText("右键按下中间图片");m_stateLabel->setStyleSheet(blueStyle);}//图片放大并显示tmpImg=m_image.transformed(matrix);m_label->setPixmap(QPixmap::fromImage(tmpImg));}//鼠标松开时恢复原始图片大小if(event->type()==QEvent::MouseButtonRelease){m_stateLabel->setText("鼠标释放图片");m_label->setPixmap(QPixmap::fromImage(m_image));m_stateLabel->setStyleSheet("");}}//事件交给上层对话框处理return QDialog::eventFilter(watched,event);
}
QMouseEvent: :buttons( )与QMouseEvent: :button( )的区别
假设你的鼠标左键已经按下。
如果移动鼠标,会发生的move事件,button返回Qt::NoButton,buttons返回LeftButton。
再按下了右键,会发生press事件,button返回RightButton,buttons返回LeftButton|RightButton
再移动鼠标,会发生move事件,button返回Qt::NoButton,buttons返回LeftButton|RightButton
再松开左键,会发生Release事件,button返回LeftButton,buttons返回RightButton
也就是说,button返回“哪个按钮发生了此事件”,buttons返回“发生事件时哪些按钮还处于按下状态”
追风赶月莫停留,平芜尽处是春山!