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 會自動管理對象的內存釋放
}