qt的工作原理:事件驱动、信号机制
qt的事件由窗口系统或是qt自身产生,用于响应各种需要处理的事务
Qevent类定义了Qt中的事件,通过enum QEvent::Type可以查询
常见需要处理的由窗口系统的QKeyEvent、QMouseEvent、QPaintEvent、QResizeEvent、QMoveEvent事件,来自系统的QTimerEvent等
处理特定事件处理器:
1.重写特定事件处理器
1.重写键盘按键按下的事件处理器 虚函数
#include <QKeyEvent>
void keyPressEvent(QKeyEvent *event);
key():返回按键的编码
text():获取按键的文件编码,返回的是QString
x():获取当前的x坐标值
switch(event->key())
{
case Qt::Key_Up:
ui->label->move(ui->label->x(),ui->label->y()-2);
break;
case Qt::Key_Down:
ui->label->move(ui->label->x(),ui->label->y()+2);
break;
case Qt::Key_Left:
ui->label->move(ui->label->x()-2,ui->label->y()-2);
break;
case Qt::Key_Right:
ui->label->move(ui->label->x()+2,ui->label->y()-2);
break;
}
-------------------------------------------------------------------------------------------------
2.重写鼠标按下的事件处理
#include <QMouseEvent>
void mouseMoveEvent(QMouseEvent *event);
鼠标特殊设备,必须按下任意按键移动时,才会产生鼠标移动事件
x():获取当前鼠标在界面的x坐标
ui->label->move(event->x()-ui->label->width()/2,event->y()-ui->label->width()/2);
设置鼠标跟随:
意味着在 widget不需要鼠标按键按下就可以产生鼠标移动事件
在构造函数中:this->setMouseTracking(true);
2.重写event函数
bool event(QEvent *event);
事件的处理流程:
1.界面产生的任何事,优先调用QWidge基类的event函数进行处理
2.event函数内部,判断事件的类型,然后调用基类的特定事件处理器进行处理
3.如果派生类重写了特定事件处理器,则event调用派生类重写的虚函数,实现新功能
注:如果派生类重写了event虚函数,则界面产生的事件优先调用派生类重写的event虚函数
1.判断自己感兴趣需要处理的事件,实现新功能,处理完返回true
2.不感兴趣的事件,则需要手动调用基类的event函数进行默认处理,返回基类处理结果
-------------------------------------------------------------------------------------------------
事件的处理流程,事件发生后首先交给级别比较高的QWidget类的event处理
再交给特定函数事件处理,但都是基于QWidget类的
bool Widget::event(QEvent *event)
{
if(event->type()==感兴趣的事件)
{
处理;
return true;
}
return QWidget::event(event);
}
-------------------------------------------------------------------------------------------------
bool Widget::event(QEvent *event)
{
if(event->type()==QKeyEvent::KeyPress)
{
keyPressEvent((QKeyEvent *)event);
return true;
}
if(event->type()==QMouseEvent::MouseMove)
{
QMouseEvent *e=(QMouseEvent *)event;
ui->label->move(e->x()-ui->label->width()/2,e->y()-ui->label->height()/2);
}
return QWidget::event(event);
}
3.注册事件过滤器,并重写过滤器
bool eventFilter(QObject *watched, QEvent *event);
事件过滤器目的是筛选出感兴趣控件上产生的感兴趣的事件
步骤:
1.重写eventFilter函数
bool eventFilter(QObject *watched, QEvent *event);
2.将关注的控件加载安装到当前类的过滤器中 installEventFilter(this);
在构造函数中:ui->textEdit->installEventFilter(this);
这样在该控件上产生的任何事件都优先调用eventFilter,不会调用event
注:在输入类控件(比如文本编辑框)中,鼠标左键不会产生MouseButtonPress事件
-------------------------------------------------------------------------------------------------
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if(watched==感兴趣的控件)
{
if(event->type()==控件上感兴趣的事件)
{
return true;
}
return QWidget::eventFilter(watched,event);
}
return QWidget::eventFilter(watched,event);
}
-------------------------------------------------------------------------------------------------
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if(watched==ui->textEdit)
{
if(event->type()==QMouseEvent::MouseButtonPress)
{
QMouseEvent *e=(QMouseEvent *)event;
#if 0
if(e->button()==Qt::LeftButton)
{
ui->label->setStyleSheet("background-color:yellow;border-radius:25px;");
}
#endif
if(e->button()==Qt::MiddleButton)
{
ui->label->setStyleSheet("background-color:yellow;border-radius:45px;");
}
if(e->button()==Qt::RightButton)
{
ui->label->setStyleSheet("background-color:green;border-radius:45px;");
}
return true;
}
return QWidget::eventFilter(watched,event);
}
return QWidget::eventFilter(watched,event);
}
二维画图
#include <QPainter>
#include <QPen>
#include <QBrush>
重写绘图事件处理器:
void paintEvent(QPaintEvent *e);
{
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
QPen pen;
pen.setColor(QColor("#aabbcc"));
pen.setStyle(Qt::SolidLine);
pen.setWidth(8);
p.setPen(pen);
p.translate(width()/2, height()/2);
p.drawLine(QPoint(150, 0), QPoint(155, 0));
p.rotate(90);
p.drawLine(QPoint(150, 0), QPoint(155, 0));
p.setBrush(QBrush("black"));
p.drawEllipse(QPoint(0, 0), 155, 155);
QPoint point[3] = {
QPoint(0, 0),
QPoint(0, 40),
QPoint(30, 0),
};
p.drawConvexPolygon(point, 3);
}
计时器
#include <QTimer>
widget.h:
private:
QTimer *time;
private slots:
void timeOut();
widget.c:
构造函数:
time = new QTimer(this);
connect(time, &QTimer::timeout, this, &Widget::timeOut);
time->start(1000);
槽函数:
void Widget::timeOut()
{
update();
}