qt中的事件
qt中的事件
一、事件介绍
1、事件是对各种应用程序需要知道的由应用程序内部或者外部产生的事情或者动作的通称。在Qt中使用 一个对象来表示一个事件,它继承自QEvent类。
常见事件:鼠标事件、键盘事件、定时事件、上下文菜单事件、关闭事件、拖放事件、绘制事件。
二、事件的处理
重载相关的Event函数
重新实现事件的paintEvent(),mousePressEvent()等事件处理函数。这是最常用也的一种方法,不过它 只能用来处理特定部件的特定事件。例如实现拖放操作,就是用的这种方法。
安装事件过滤器
在对象上安装事件过滤器。使用事件过滤器可以在一个界面类中同时处理不同子部件的不同事件。
三、常见事件
1、键盘事件
QKeyEvent
QKeyEvent类用来描述一个键盘事件。当键盘按键被按下或者被释放时,键盘事件便会被发送给拥有键 盘输入焦点的部件。
在Qt助手中,查找一下Qt::Key,这里会有的一些Qt::Key_Escape表示空格,Qt::Key_Left←键等等
1.1找到keyPressEvent
需要包含头文件才能用,下面是从头文件中拿出来的
protected:
bool event(QEvent *event) Q_DECL_OVERRIDE;
virtual void mousePressEvent(QMouseEvent *event);//鼠标按下
virtual void mouseReleaseEvent(QMouseEvent *event);//鼠标释放
virtual void mouseDoubleClickEvent(QMouseEvent *event);//鼠标双击
virtual void mouseMoveEvent(QMouseEvent *event);//鼠标移动
#ifndef QT_NO_WHEELEVENT
virtual void wheelEvent(QWheelEvent *event); //滚轮
#endif
virtual void keyPressEvent(QKeyEvent *event);//按键按下
virtual void keyReleaseEvent(QKeyEvent *event);//按键释放
virtual void enterEvent(QEvent *event);//进入
virtual void leaveEvent(QEvent *event);//离开
virtual void paintEvent(QPaintEvent *event);//绘制
virtual void moveEvent(QMoveEvent *event);//离开
这里父类是怎么定义和声明的虚函数,我们就怎么实现它:
//自己的类中去定义,然后实现
protected:
virtual void keyPressEvent(QKeyEvent *event);//按键按下
1.2判断某个键按下
void Widget::keyPressEvent(QKeyEvent *event)
{
if(event->key()==Qt::Key_X)
{
qDebug()<<"X按下";
}
}
1.3组合键操作
在Qt助手中搜索Qt::KeyboardModifier,如下
void Widget::keyPressEvent(QKeyEvent *event)
{
if(event->modifiers()==Qt::ControlModifier)//判断是不是ctrl按下
{
if(event->key()==Qt::Key_X)//接着判断是不是x按下
{
qDebug()<<"ctrl+X";
}
}
else if(event->key()==Qt::Key_X)
{
qDebug()<<"X按下";
}
}
2、鼠标事件
QMouseEvent类用来表示一个鼠标事件,当在窗口部件中按下鼠标或者移动鼠标指针时,都会产生鼠 标事件。利用QMouseEvent类可以获知鼠标是哪个键按下了,还有鼠标指针的当前位置等信息。通常是 重定义部件的鼠标事件处理函数来进行一些自定义的操作。
QWheelEvent类用来表示鼠标滚轮事件,在这个类中主要是获取滚轮移动的方向和距离。在滚轮事件 处理函数中,使用QWheelEvent类的delta()函数获取了滚轮移动的距离,每当滚轮旋转一下,默认的是 15度,当滚轮向远离使用者的方向旋转时,返回正值;当向着靠近使用者的方向旋转时,返回负值。这 样便可以利用这个函数的返回值来判断滚轮的移动方向。
Qt::LeftButton //左
Qt::RightButton //中
Qt::MidButton //右
2.1鼠标单击事件
void Widget::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
qDebug()<<"左键按下";
}
}
2.2鼠标释放事件
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
qDebug()<<"左键释放";
}
}
2.3鼠标双击事件
void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
qDebug()<<"左键双击";
}
}
注意:第一次输出左键按下
2.4鼠标移动事件
setMouseTracking(true);
这个默认是为false,需要设置为true,这样才能实时获取鼠标位置,要不然 只有在按下的时候才能获取到
void Widget::mouseMoveEvent(QMouseEvent *event)
{
qDebug()<<event->x()<<event->y();
qDebug()<<event->pos();//相对于窗口的坐标
qDebug()<<event->globalPos();//相对于屏幕的坐标
}
2.5滚轮事件
void Widget::wheelEvent(QWheelEvent *event)
{
static int x=0;
x+=event->delta();// ±120
//求滚动次数
static int a = 0;//次数
int sum=event->delta();
a +=sum/120;
if(event->delta()>0)
{
qDebug()<<"滚轮往前"<<x;
qDebug()<<a;
}
else
{
qDebug()<<"滚轮往后"<<x;
qDebug()<<a;
}
}
3、事件过滤器
就是说有事件产生,在这个控件上只处理什么事件
在左边输入abcd那么是不会输入到里面去的,会被事件过滤器去获取
3.1安装事件过滤器
ui->textEdit->installEventFilter(this);
3.2事件的过滤器实现
//声明函数
virtual bool eventFilter(QObject *watched, QEvent *event);
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if(watched==ui->textEdit)//通过watched来监视控件
{
if(event->type()==QEvent::KeyPress)//是不是按键按下
{
QKeyEvent *keyEvent=static_cast<QKeyEvent*>(event);//强转
qDebug()<<keyEvent->key();//输出按下的键
return true;
}
else
return false;
}
return Widget::eventFilter(watched,event);//这个函数需要一直在监视所以这里是一个递归
}
如果是其他的控件,也是同样的做法
再添加了一个pushbutton,如果添加信号和槽,没加过滤器之前,按下就输出一个按下
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if(watched==ui->textEdit)
{
if(event->type()==QEvent::KeyPress)//是不是按键按下
{
QKeyEvent *keyEvent=static_cast<QKeyEvent*>(event);
qDebug()<<keyEvent->key();
return true;
}
else
return false;
}
//在后面接着判断看这个监视的是不是pushbutton
if(watched==ui->pushButton)
{
if(event->type()==QEvent::MouseButtonPress)
{
qDebug()<<"过滤器输出了";
return true;
}
else
return false;
}
return Widget::eventFilter(watched,event);
}
4、定时器
QTimerEvent类用来描述一个定时器事件。对于一个QObject的子类,只需要使用int QObject::startTimer ( int interval )函数来开启一个定时器,这个函数需要输入一个以毫秒为单位的整数 作为参数来表明设定的时间,它返回一个整型编号来代表这个定时器。当定时器溢出时就可以在 timerEvent()函数中获取该定时器的编号来进行相关操作。
QTimer类来实现一个定时器,它提供了更高层次的编程接口,比如可以使用信号和槽,还可以设置只 运行一次的定时器。
4.1 QTimerEvent定时器
设置定时器
int id1;
int id2;
int id3;
int id4;
设置时间
id1=startTimer(1000);//1000毫秒
id2=startTimer(2000);
id3=startTimer(3000);
id4=startTimer(4000);
函数实现
virtual void timerEvent(QTimerEvent *event);
void Widget::timerEvent(QTimerEvent *event)
{
if(event->timerId()==id1)
{
qDebug()<<"id1";
}
if(event->timerId()==id2)
{
qDebug()<<"id2";
}
if(event->timerId()==id3)
{
qDebug()<<"id3";
}
if(event->timerId()==id4)
{
qDebug()<<"id4";
}
}
4.2 QTimer定时器
设置定时器
QTimer t1;
QTimer t2;
设置时间
t1.start(1000);//1000毫秒
t2.start(2000);
管联信号和槽:
这里的槽函数,指的是这个时间到了要执行什么函数
private slots:
void qDebugSlot1();
void qDebugSlot2();
void Widget::qDebugSlot1()
{
qDebug()<<"t1";
}
void Widget::qDebugSlot2()
{
qDebug()<<"t2";
}
connect(&t1,SIGNAL(timeout()),this,SLOT(qDebugSlot1()));
connect(&t2,SIGNAL(timeout()),this,SLOT(qDebugSlot2()));
5、随机数种子
在使用qrand()函数产生随机数之前,一般要使用qsrand()函数为其设置初值,如果不设置初值,那么 每次运行程序,qrand()都会产生相同的一组随机数。
为了每次运行程序时,都可以产生不同的随机数, 我们要使用qsrand()设置一个不同的初值。
qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));//设置随机数种子
int rand = qrand() % 300;//获取随机数
6、幸运大转盘
就通过旋转盘来完成随机的抽奖,加旋转多少度,和不加旋转多少度,会有轻微的区别
void Widget::paintEvent(QPaintEvent *event)
{
painter.begin(this); //开始
painter.translate(200,200); //改变原点坐标窗口中心
painter.drawPixmap(-200,-200,400,400,QPixmap(":/image/luck.png"));//绘图
painter.rotate(radian); //旋转多少度
painter.drawImage(-200,-200,QImage(":/image/jiantou.png"));//绘图
//painter.setOpacity(0.5);
painter.end(); //结束
radian++;
if(radian>=361)
{
radian=1;
}
}
然后这样只是旋转了,这个盘,然后稍做一点优化,在原来的基础上在贴一个箭头的图片,和拖入一个 pushbutton,注意图片的要是png透明格式的 然后只需要设置定义器旋转这个箭头就可以了,点开始就旋转,停止就停下来
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了