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_OBJECTpublic: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 初始化为 falsepix = 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; // 初始化索引为0files = QFileDialog::getOpenFileNames(); // 获取选择的图片文件列表QPixmap pix(files[index]); // 加载第一张图片lb->setPixmap(pix); // 在 QLabel 上显示图片}void showr() // 显示下一张图片槽函数{if(index+1 < files.length()) // 判断是否还有下一张图片index++;elseindex = 0; // 循环显示图片QPixmap pix(files[index]); // 加载指定索引的图片lb->setPixmap(pix); // 在 QLabel 上显示图片}void showl() // 显示上一张图片槽函数{if(index-1 >= 0) // 判断是否还有上一张图片index--;elseindex = 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 会自动管理对象的内存释放
}