Qt是以事件来驱动的,类似鼠标点击、按下键盘等都是属于事件。Qt将所有的事件都抽象成QEvent
类,其它各种各样的事件都继承自QEvent
QEvent
继承自QWidget
。
通过Qt助手
搜索QWidget查看
其Protected Functions
一栏可以支持的事件。事件基本都是受保护的虚函数。虚函数
在C++中用于实现多态
,所以可以重写实现对特定事件的处理。
窗口事件
-
离开事件
[virtual protected] void QWidget::leaveEvent(QEvent *event)
-
进入事件
[virtual protected] void QWidget::enterEvent(QEvent *event)
-
事件分发
[virtual protected] bool QWidget::event(QEvent *event)
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public:
void leaveEvent(QEvent *event); //重写的离开事件
void enterEvent(QEvent *event); //重写进入事件
bool event(QEvent *event); //重写事件分发
private:
Ui::Widget *ui;
};
void Widget::leaveEvent(QEvent *event)
{
qDebug() << "鼠标进入了主窗口";
}
void Widget::enterEvent(QEvent *event)
{
qDebug() << "鼠标离开了主窗口";
}
bool Widget::event(QEvent *event)
{
if (event->type() == QEvent::MouseButtonDblClick) //鼠标双击事件
{
qDebug() << "双击了主窗口";
return true; //表示我已经处理,不向下分发MouseButtonDblClick事件
//可以对事件做一个拦截
}
return QWidget::event(event); //其他情况默认处理
}
鼠标事件
鼠标事件相关的类:QMouseEvent
-
鼠标移动事件:
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event)
-
鼠标按下事件:
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)
-
鼠标释放事件:
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event)
-
鼠标双击事件:
[virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
class myPushButton : public QPushButton
{
Q_OBJECT
public:
explicit myPushButton(QWidget *parent = nullptr);
public:
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *e);
void mouseDoubleClickEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *e);
signals:
public slots:
};
#include "mypushbutton.h"
#include <QDebug>
myPushButton::myPushButton(QWidget *parent) : QPushButton(parent)
{
setMouseTracking(true); //设置鼠标追踪,不按下鼠标键就触发鼠标移动事件
}
void myPushButton::mouseDoubleClickEvent(QMouseEvent *event)
{
qDebug() << "鼠标双击了按钮";
}
//设置鼠标追踪才能看到鼠标移动事件
void myPushButton::mouseMoveEvent(QMouseEvent *event)
{
qDebug() << "鼠标在按钮上移动";
}
void myPushButton::mousePressEvent(QMouseEvent *e)
{
qDebug() << "鼠标按下了按钮";
}
void myPushButton::mouseReleaseEvent(QMouseEvent *e)
{
qDebug() << "鼠标释放了按钮";
}
鼠标分左键、右键、中键等,对鼠标事件有时还得区分是哪个键双击、按下,还有组合键的情况。
- Qt助手搜索
QMouseEvent
,可知鼠标判断是哪个键执行的函数:
Qt::MouseButton QMouseEvent::button() const
//Returns the button that caused the event.//返回引起事件的按钮
Qt::MouseButtons QMouseEvent::buttons() const
//Returns the button state when the event was generateds
-
Qt::MouseButton
枚举:主要是以下几个
1、Qt::LeftButton //左键
2、Qt::RightButton //右键
3、Qt::MidButton //中键
.....
void myPushButton::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
qDebug() << "鼠标左键双击了按钮";
}
}
//设置鼠标追踪才能看到鼠标移动事件
void myPushButton::mouseMoveEvent(QMouseEvent *event)
{
qDebug() << "鼠标在按钮上移动";
}
void myPushButton::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::RightButton)
qDebug() << "鼠标右键按下了按钮";
}
void myPushButton::mousePressEvent(QMouseEvent *event)
{
// if (event->button() == Qt::RightButton)
// qDebug() << "鼠标右键按下了按钮";
// if (event->buttons() == Qt::RightButton)
// {
// qDebug() << "鼠标右键按下了按钮";
// }
if (event->buttons() & Qt::RightButton)
{
qDebug() << "鼠标右键按下了按钮";
}
}
对鼠标的处理中还有很多其他的处理,可以精准到对鼠标所在的位置。
-
鼠标位置相关的方法:
int x() const int y() const QPoint pos() const
void myPushButton::mouseMoveEvent(QMouseEvent *event) { qDebug() << "鼠标在按钮上移动"; QString str = QString("鼠标的位置:x = %1 y = %2").arg(event->x()).arg(event->y()); qDebug() << str; }
定时器事件
定时器相关的类:QTimer
、QTimerEvent
-
定时器事件
[virtual protected] void QTimer::timerEvent(QTimerEvent *e)
启动定时器两种方式:
- 第一种:
int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)
//返回值是定时器的id
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
timerId1 = startTimer(1000); //启动定时器
timerId2 = startTimer(2000);
}
//重写定时器事件
void Widget::timerEvent(QTimerEvent *event)
{
if (event->timerId() == timerId2)
{
qDebug() << "2s时间到";
}
if (event->timerId() == timerId1)
{
qDebug() << "1s时间到";
}
}
-
第二种:
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); QTimer *timer = new QTimer; //创建一个定时器 timer->start(3000); //启动 connect(timer, &QTimer::timeout, [=](){ qDebug() << "3s时间到"; }); //设置信号、槽,槽使用lamda表达式 }
键盘事件
键盘事件的类:QKeyEvent
-
键盘按下
[virtual protected] void QWidget::keyPressEvent(QKeyEvent *event)
-
键盘释放
[virtual protected] void QWidget::keyReleaseEvent(QKeyEvent *event)
-
判断哪个按键按下
int QKeyEvent::key() const //Returns the code of the key that was pressed or released.
通过
Qt::Key
里面的枚举值判断是哪个按键按下。
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
private:
Ui::Widget *ui;
};
void Widget::keyPressEvent(QKeyEvent *event)
{
if (event->key() & Qt::Key_Enter) //如果按下回车键
{
qDebug() << "按下了回车键";
}
}
void Widget::keyReleaseEvent(QKeyEvent *event)
{
if (event->key() & Qt::Key_Enter) //如果按下回车键
{
qDebug() << "释放了回车键";
}
}
设置焦点窗口:
当只有一个窗口时,键盘事件就是给当前窗口的。当有多个窗口时,需要指定一个焦点窗口来接收键盘事件。
void QWidget::setFocus(Qt::FocusReason reason);
//reason 焦点切换的原因,一般是Qt::OtherFocusReason即可
事件过滤器
事件只能在自己的类中处理,如果其它对象想知道某个窗口的事件,需要给窗口安装事件过滤器
安装事件过滤器:
void QObject::installEventFilter(QObject *filterObj)
//filterObj 监控者
事件过滤函数:
[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event)
//watch 监控对象
//event 事件
//返回true表示过滤事件,false表示不过滤
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
cirX = 0;
connect(ui->pushButton, &QPushButton::clicked, [=](){
cirX++;
// update(); //手动绘图,调用update更新
repaint();
});
ui->pushButton->installEventFilter(this); //安装事件过滤器
}
//重写事件过滤处理函数
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if (watched == ui->pushButton)
{
if (event->type() == QEvent::MouseButtonDblClick)
{
qDebug() << "过滤按钮上的鼠标双击事件";
return true; //返回true表示过滤事件
}
}
return QWidget::eventFilter(watched, event); //其他情况使用默认处理
}
绘图事件
绘图事件:
[virtual protected] void QWidget::paintEvent(QPaintEvent *event)
绘图事件函数是一直被调用。用户不重写绘图事件就什么都不绘制。当用户重写该函数就执行用户的实现。
void Widget::paintEvent(QPaintEvent *event)
{
QPainter *myPainter = new QPainter(this);
QPen pen(QColor(255, 0, 0)); //创建一个画笔
pen.setWidth(3); //设置画笔宽度
myPainter->setPen(pen); //设置画笔
QBrush brush(Qt::cyan); //设置画刷
//设置画刷风格
brush.setStyle(Qt::Dense7Pattern);
//让画家使用画刷
myPainter->setBrush(brush);
myPainter->drawLine(20, 20, 50, 60); //画线
myPainter->drawEllipse(40, 40, 50, 60); //画圆
}
重绘:
[slot] void QWidget::repaint() //立即重启
[slot] void QWidget::update() //不立马重绘,而是加入消息循环来调度
#include <QPen>
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
cirX = 0;
//通过按钮手动绘图
connect(ui->pushButton, &QPushButton::clicked, [=](){
cirX++;
// update(); //手动绘图,调用update更新
repaint();
});
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter *myPainter = new QPainter(this);
QPen pen(QColor(255, 0, 0)); //创建一个画笔
pen.setWidth(3); //设置画笔宽度
myPainter->setPen(pen); //设置画笔
myPainter->drawEllipse(40+cirX, 40, 50, 60); //画圆。圆会随着按钮移动而移动
}