1 事件模型
2 事件处理
virtual void keyPressEvent(QKeyEvent *event)
virtual void keyReleaseEvent(QKeyEvent *event)
virtual void mouseDoubleClickEvent(QMouseEvent *event)
virtual void mouseMoveEvent(QMouseEvent *event)
virtual void mousePressEvent(QMouseEvent *event)
virtual void mouseReleaseEvent(QMouseEvent *event)
virtual void moveEvent(QMoveEvent *event)
virtual void paintEvent(QPaintEvent *event)
virtual void resizeEvent(QResizeEvent *event)
virtual void wheelEvent(QWheelEvent *event)
2.1 事件综合示例
- mousePressEvent:处理鼠标按下事件,输出鼠标位置信息。
- mouseMoveEvent:处理鼠标移动事件,输出鼠标位置信息。
- keyPressEvent:处理键盘按下事件,输出按下的键值。
- wheelEvent:处理鼠标滚轮事件,输出滚轮滚动距离。
- timerEvent:处理定时器事件,输出定时器事件信息。
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QWheelEvent>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
void mousePressEvent(QMouseEvent *event)
{
qDebug()<<"pressssss: "<<event->pos();
}
void mouseMoveEvent(QMouseEvent *event)
{
qDebug()<<"moving!"<<event->pos();
}
void keyPressEvent(QKeyEvent *event)
{
qDebug()<<"key: "<<event->key();
}
void wheelEvent(QWheelEvent *event)
{
qDebug()<<"wheel: "<<event->delta();
}
void timerEvent(QTimerEvent *event)
{
qDebug()<<"timer!";
}
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
startTimer(1000);
}
Widget::~Widget()
{
}
2.2 绘图事件
virtual void paintEvent(QPaintEvent *event)
{
if(isDrawing) {
tempPix = pix; //双缓冲
QPainter pp(&tempPix);
painter.drawPixmap(0,0,tempPix);
}
else {
QPainter pp(&pix);
painter.drawPixmap(0,0,pix);
}
}
绘制时钟示例
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
#include <QPainter>
class Widget : public QWidget
{
Q_OBJECT // 使用 Q_OBJECT 宏,以便能够使用 Qt 的信号和槽机制
public:
Widget(QWidget *parent = 0); // 构造函数
~Widget(); // 析构函数
void paintEvent(QPaintEvent *event) // 重载 paintEvent 方法,用于绘制图形
{
qDebug()<<"ppppppp"; // 输出调试信息
QPainter p(this); // 创建 QPainter 对象并将当前窗口部件作为绘图设备
p.translate(this->width()/2, this->height()/2); // 将坐标系平移到窗口中心
p.drawEllipse(QPoint(0, 0), 100, 100); // 绘制椭圆
// p.drawLine(0, 0, 50, 50); // 注释掉的代码,不会被执行
p.rotate(i++*10); // 旋转坐标系
p.drawLine(0, 0, 50, 50); // 绘制旋转后的线条
}
void timerEvent(QTimerEvent *event) // 重载 timerEvent 方法,处理定时器事件
{
update(); // 更新界面
}
private:
int i; // 用于记录旋转角度的变量
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
i = 0;
startTimer(1000);
}
Widget::~Widget()
{
}
效果
示例2
用于实现一个简单的画板功能。用户可以在窗口上按下鼠标左键开始绘制线条,拖动鼠标绘制线条,松开鼠标左键结束绘制。
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QMouseEvent>
#include <QPainter>
class Widget : public QWidget
{
Q_OBJECT // 使用 Q_OBJECT 宏,以便能够使用 Qt 的信号和槽机制
public:
Widget(QWidget *parent = 0); // 构造函数
~Widget(); // 析构函数
void mousePressEvent(QMouseEvent *event) // 处理鼠标按下事件
{
startp = event->pos(); // 记录鼠标按下时的位置
}
void mouseReleaseEvent(QMouseEvent *event) // 处理鼠标释放事件
{
saveit = true; // 标记需要保存当前绘制的线条
update(); // 更新界面
}
void mouseMoveEvent(QMouseEvent *event) // 处理鼠标移动事件
{
endp = event->pos(); // 记录鼠标移动时的位置
update(); // 更新界面
}
void paintEvent(QPaintEvent *event) // 重载 paintEvent 方法,用于绘制图形
{
if(saveit)
{
QPainter px(pix); // 创建一个新的 QPainter 对象
px.drawLine(startp, endp); // 在 QPixmap 对象上绘制线条,否则下一个线条会消失
saveit = false; // 将保存标志复位
}
QPainter p(this); // 创建一个 QPainter 对象,绘制到当前窗口部件上
p.drawPixmap(0, 0, *pix); // 将 QPixmap 对象绘制到窗口上
p.drawLine(startp, endp); // 实时显示当前绘制的线条
}
private:
QPoint startp; // 起始点坐标
QPoint endp; // 终点坐标
QPixmap *pix; // 用于保存绘制内容的 QPixmap 对象
bool saveit; // 标志是否需要保存当前绘制的线条
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//创建了一个与窗口大小相同的 QPixmap 对象,并将其填充为白色背景。同时,将保存标志 saveit 初始化为 false
pix = new QPixmap(this->width(), this->height());
pix->fill();
saveit = false;
}
Widget::~Widget()
{
}
3 事件过滤
class A:public Qobject{
};
class B:public Qobject{
Public:
bool eventFilter(Qobject *sender, Qevent *event){
return QObject::eventFilter(obj, event);
}
};
A x;
B y;
x.installeventfilter(&y);
事件示例
一个事件,如先进过快捷键,后经过按钮。最终效果键盘可以切换图片,按钮也可以切换
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QFileDialog>
#include <QStringList>
#include <QEvent>
#include <QKeyEvent>
class Widget : public QWidget
{
Q_OBJECT // 使用 Q_OBJECT 宏,以便能够使用 Qt 的信号和槽机制
public slots:
void openfiles() // 打开图片文件槽函数
{
index = 0; // 初始化索引为0
files = QFileDialog::getOpenFileNames(); // 获取选择的图片文件列表
QPixmap pix(files[index]); // 加载第一张图片
lb->setPixmap(pix); // 在 QLabel 上显示图片
}
void showr() // 显示下一张图片槽函数
{
if(index+1 < files.length()) // 判断是否还有下一张图片
index++;
else
index = 0; // 循环显示图片
QPixmap pix(files[index]); // 加载指定索引的图片
lb->setPixmap(pix); // 在 QLabel 上显示图片
}
void showl() // 显示上一张图片槽函数
{
if(index-1 >= 0) // 判断是否还有上一张图片
index--;
else
index = files.length()-1; // 循环显示图片
QPixmap pix(files[index]); // 加载指定索引的图片
lb->setPixmap(pix); // 在 QLabel 上显示图片
}
bool eventFilter(QObject *watched, QEvent *event) // 事件过滤器函数
{
lb->setFocus(); // 设置 QLabel 获得焦点
if(watched == lb) // 如果事件源是 QLabel
{
if(event->type() == QEvent::KeyPress) // 如果是键盘按键事件
{
QKeyEvent *keyevent = static_cast<QKeyEvent*>(event); // 将事件转换为键盘事件
if(keyevent->key() == Qt::Key_Left) // 如果按下左箭头键
showl(); // 显示上一张图片
else if(keyevent->key() == Qt::Key_Right) // 如果按下右箭头键
showr(); // 显示下一张图片
return true; // 返回 true 表示事件已处理
}
}
return QWidget::eventFilter(watched, event); // 其他情况交给父类处理
}
public:
Widget(QWidget *parent = 0); // 构造函数
~Widget(); // 析构函数
private:
QLabel *lb; // 显示图片的 QLabel 对象
QPushButton *lbt, *rbt, *openbt; // 左右切换和打开文件的按钮
QStringList files; // 存储打开的图片文件列表
int index; // 当前显示图片的索引
};
#endif // WIDGET_H
widget.cpp
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
// 创建 QLabel 控件,并设置大小、缩放内容以及获取焦点
lb = new QLabel;
lb->setMinimumSize(640, 480);
lb->setScaledContents(true);
lb->setFocus();
lb->installEventFilter(this); // 安装事件过滤器,用于处理键盘事件
// 创建左右切换和打开文件的按钮,并添加到水平布局中
lbt = new QPushButton("<");
rbt = new QPushButton(">");
openbt = new QPushButton("open");
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addStretch();
hbox->addWidget(lbt);
hbox->addWidget(openbt);
hbox->addWidget(rbt);
hbox->addStretch();
// 创建垂直布局,将 QLabel 和水平布局添加到其中,并设置为 Widget 的布局
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(lb);
vbox->addLayout(hbox);
setLayout(vbox);
index = 0; // 初始化索引为0
// 连接按钮的点击信号与槽函数
connect(openbt, SIGNAL(clicked(bool)), this, SLOT(openfiles())); // 打开文件按钮
connect(lbt, SIGNAL(clicked(bool)), this, SLOT(showl())); // 左箭头按钮
connect(rbt, SIGNAL(clicked(bool)), this, SLOT(showr())); // 右箭头按钮
}
Widget::~Widget()
{
// 析构函数为空,因为 Qt 会自动管理对象的内存释放
}