11.1 鼠标事件及实例
鼠标事件包括鼠标的移动,鼠标键按下、松开、单击、双击等。
运行效果如下:
mouseevent.h
#ifndef MOUSEEVENT_H
#define MOUSEEVENT_H
#include
#include
#include
#include
class MouseEvent : public QMainWindow
{
Q_OBJECT
public:
MouseEvent(QWidget *parent = 0);
~MouseEvent();
protected:
void mouseMoveEvent (QMouseEvent *);
void mousePressEvent (QMouseEvent *);
void mouseReleaseEvent (QMouseEvent *);
void mouseDoubleClickEvent (QMouseEvent *);
private:
QLabel *statusLabel;
QLabel *MousePosLabel;
};
#endif // MOUSEEVENT_H
mouseevent.cpp
#include "mouseevent.h"
/*
* statusBar()->addPermanentWidget(statusLabel): 在QMainWindow的状态栏中增加控件
* this->setMouseTracking (true):设置窗体追踪鼠标。函数setMouseTracking()设置窗体是否追踪鼠标,默认为false,不追踪
* 在此情况下应该至少有一个鼠标按键按下时响应鼠标移动的事件,
*/
MouseEvent::MouseEvent(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle (tr("鼠标事件"));
statusLabel = new QLabel(tr("当前位置"));
statusLabel->setFixedWidth (100);
MousePosLabel = new QLabel(tr(""));
MousePosLabel->setFixedWidth (100);
statusBar()->addPermanentWidget(statusLabel);
statusBar()->addPermanentWidget(MousePosLabel);
this->setMouseTracking (true);
resize(400, 200);
}
MouseEvent::~MouseEvent()
{
}
/*
* 鼠标按下响应函数
* QMouseEvent类的x()和y()方法可以获得鼠标相对于接收事件的窗体位置,
* globalX()和globalY()方法可以获得鼠标相对于窗口系统的位置
*/
void MouseEvent::mousePressEvent(QMouseEvent *e)
{
QString str = "(" + QString::number (e->x ()) + ", " + QString::number (e->y ()) + ")";
if(e->button () == Qt::LeftButton)
{
statusBar ()->showMessage (tr("左键::") + str);
}
else if(e->button () == Qt::RightButton)
{
statusBar ()->showMessage (tr("右键:") + str);
}
else if(e->button () == Qt::MidButton)
{
statusBar ()->showMessage (tr("中键:") + str);
}
}
/*
* 鼠标移动响应函数
*/
void MouseEvent::mouseMoveEvent(QMouseEvent *e)
{
MousePosLabel->setText ("(" + QString::number (e->x ()) + ", " + QString::number (e->y ()) + ")");
}
void MouseEvent::mouseReleaseEvent(QMouseEvent *e)
{
QString str = "(" + QString::number (e->x ()) + ", " + QString::number (e->y ()) + ")";
statusBar ()->showMessage (tr("释放在:") + str);
}
void MouseEvent::mouseDoubleClickEvent (QMouseEvent *e)
{
}
11.2 键盘事件及实例
在图像处理和游戏应用程序中,有时需要通过键盘控制某个对象的移动,此功能可以通过对键盘事件的处理来实现。键盘事件的获取是通过重定义QWidget类的
keyPressEvent()和KeyReleaseEvent()来实现。
通过键盘的上、下、左、右方向可以控制图标的移动,移动的步进值为网络的大小,如果同时按下[Ctrl]键,则实现细微移动:若按下[Home]键,则光标回到界
面的左上点;若按下[End]键,则光标到达界面的右下点。
运行效果
keyevent.h
#ifndef KEYEVENT_H
#define KEYEVENT_H
#include
#include
#include
class KeyEvent : public QWidget
{
Q_OBJECT
public:
KeyEvent(QWidget *parent = 0);
~KeyEvent();
void drawPix();
void keyPressEvent (QKeyEvent *);
void paintEvent (QPaintEvent *);
private:
QPixmap *pix; //作为一个绘图设备,使用双缓冲机制实现图形的绘制
QImage image; //界面中间的小图标
int startx; //图标的左上顶点位置
int starty;
int width; //界面的宽度和高度
int height;
int step; //网格的大小,及移动的步进值
};
#endif // KEYEVENT_H
keyevent.cpp
#include "keyevent.h"
#include
KeyEvent::KeyEvent(QWidget *parent)
: QWidget(parent)
{
setWindowTitle (tr("键盘事件"));
setAutoFillBackground (true);
QPalette palette = this->palette ();
palette.setColor (QPalette::Window, Qt::white);
setPalette (palette);
setMinimumSize (525, 265);
setMaximumSize (525, 265);
width = size().width ();
height = size().height ();
pix = new QPixmap(width, height);
pix->fill (Qt::white);
image.load ("../image/image.png");
startx = 100;
starty = 100;
step = 20;
drawPix ();
resize (525, 265);
}
KeyEvent::~KeyEvent()
{
}
void KeyEvent::drawPix ()
{
pix->fill (Qt::white); //重新刷新pix对象为白色底色
QPainter *painter = new QPainter; //创建一个QPainter对象
QPen pen(Qt::DotLine); //设置画笔的风格,用于绘制网络表格
for(int i = step; i <= 520; i += step)
{
for(int j = step; j <= 260; j += step)
{
painter->begin (pix);
painter->setPen (pen);
painter->drawLine (QPoint(i, 20), QPoint(i, 260));
painter->drawLine (QPoint(20, j), QPoint(520, j));
painter->end ();
}
}
painter->begin (pix);
/*在pix对象中绘制可移动的小图标*/
painter->drawImage (QPoint(startx, starty), image);
painter->end ();
}
void KeyEvent::keyPressEvent (QKeyEvent *e)
{
if(e->modifiers () == Qt::ControlModifier)
{
if(e->key () == Qt::Key_Left)
{
startx = (startx - 1 < 21) ? startx : startx - 1;
}
if(e->key () == Qt::Key_Right)
{
startx = (startx + 1 + image.width () > width - 5) ? startx : startx + 1;
}
if(e->key () == Qt::Key_Up)
{
starty = (starty - 1 < 21) ? starty : starty - 1;
}
if(e->key () == Qt::Key_Down)
{
starty = (starty + 1 + image.width () > height - 5) ? starty : starty + 1;
}
}
else
{
/*首先调节图标左上顶点的位置至网络的顶点上*/
startx = startx - startx % step;
starty = starty - starty % step;
if(e->key () == Qt::Key_Left)
{
startx = (startx - step < 1) ? startx + 1 : startx - step;
}
if(e->key () == Qt::Key_Right)
{
startx = (startx + step + image.width () > width - 5) ? startx : startx + step;
}
if(e->key () == Qt::Key_Up)
{
starty = (starty - step < 1) ? starty + 1 : starty - step;
}
if(e->key () == Qt::Key_Down)
{
starty = (starty + step + image.width () > height - 5) ? starty : starty + step;
}
if(e->key () == Qt::Key_Home)
{
startx = 21;
starty = 21;
}
if(e->key () == Qt::Key_End)
{
startx = 520 - image.width ();
starty = 260 - image.height ();
}
}
drawPix (); //根据调整后的图标位置重新在pix中绘制图像
update (); //触发界面重画
}
/*
* 界面重画函数paintEvent(),将pix绘制在界面上。
*/
void KeyEvent::paintEvent (QPaintEvent *p)
{
QPainter painter;
painter.begin (this);
painter.drawPixmap (QPoint(-10, -10), *pix);
painter.end ();
}
11.3事件过滤及实例
Qt的事件模型中提供的事件过滤器功能使得一个QObject对象可以监视另一个QObject对象中的事件,通过在一个QObject对象中安装事件过滤器,可以在事件到达该对象
前捕获事件,从而起到监视该对象事件的效果。
运行效果如下:
eventfilter.h
#ifndef EVENTFILTER_H
#define EVENTFILTER_H
#include
#include
#include
#include
class EventFilter : public QDialog
{
Q_OBJECT
public:
EventFilter(QWidget *parent = 0);
~EventFilter();
public slots:
bool eventFilter (QObject *, QEvent *);
private:
QLabel *label1;
QLabel *label2;
QLabel *label3;
QLabel *stateLabel;
QImage Image1;
QImage Image2;
QImage Image3;
};
#endif // EVENTFILTER_H
eventfilter.cpp
#include "eventfilter.h"
#include
#include
#include
#include
EventFilter::EventFilter(QWidget *parent)
: QDialog(parent)
{
setWindowTitle (tr("事件过滤"));
label1 = new QLabel;
Image1.load ("../image3/1.png");
label1->setAlignment (Qt::AlignHCenter | Qt::AlignVCenter);
label1->setPixmap (QPixmap::fromImage (Image1));
label2 = new QLabel;
Image2.load ("../image3/2.png");
label2->setAlignment (Qt::AlignHCenter | Qt::AlignVCenter);
label2->setPixmap (QPixmap::fromImage (Image2));
label3 = new QLabel;
Image3.load ("../image3/3.png");
label3->setAlignment (Qt::AlignHCenter | Qt::AlignVCenter);
label3->setPixmap (QPixmap::fromImage (Image3));
stateLabel = new QLabel(tr("鼠标按下标志"));
stateLabel->setAlignment (Qt::AlignHCenter);
QHBoxLayout *HBoxLayout = new QHBoxLayout;
HBoxLayout->addWidget (label1);
HBoxLayout->addWidget (label2);
HBoxLayout->addWidget (label3);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout (HBoxLayout);
mainLayout->addWidget (stateLabel);
/*为每一个图片安装事件过滤器,指定窗体为监视事件的对象*/
label1->installEventFilter (this);
label2->installEventFilter (this);
label3->installEventFilter (this);
}
EventFilter::~EventFilter()
{
}
/*
* void QObject::installEventFilter
* (
* QObject *filterObj
* )
* 参数filterObj是监视事件的对象,此对象可以通过eventFilter()函数接收事件。如果某个事件参数被过滤,即停止正常的
* 事件响应,则在eventFilter()函数中返回true,否则返回false,QObject的removeEventFilter()可以解除已安装的
* 事件过滤器。QObject的事件监视函数eventFilter()的具体实现代码
*/
bool EventFilter::eventFilter (QObject *watched, QEvent *event)
{
//首先判断当前发生事件的对象
if(watched == label1)
{
//判断发生的事件类型
if(event->type () == QEvent::MouseButtonPress)
{
//将事件event转化为鼠标事件
QMouseEvent *mouseEvent = (QMouseEvent*) event;
if(mouseEvent->buttons () == Qt::LeftButton)
{
stateLabel->setText (tr("左键按下左图片"));
}
else if(mouseEvent->buttons () == Qt::MidButton)
{
stateLabel->setText (tr("中间按键按下左图片"));
}
else if(mouseEvent->buttons () == Qt::RightButton)
{
stateLabel->setText (tr("右键按下左图片"));
}
QMatrix matrix;
matrix.scale (1.8, 1.8);
QImage newImage = Image1.transformed (matrix);
label1->setPixmap (QPixmap::fromImage (newImage));
}
/*鼠标释放的处理,恢复图片的大小*/
if(event->type () == QEvent::MouseButtonRelease)
{
stateLabel->setText (tr("鼠标释放左图片"));
label1->setPixmap (QPixmap::fromImage (Image1));
}
}
else if(watched == label2)
{
if(event->type () == QEvent::MouseButtonPress)
{
QMouseEvent *mouseEvent = (QMouseEvent*)event;
if(mouseEvent->buttons () == Qt::LeftButton)
{
stateLabel->setText (tr("左键按下中间图标"));
}
else if(mouseEvent->buttons () == Qt::MidButton)
{
stateLabel->setText (tr("中间按键按下中间图片"));
}
else if(mouseEvent->buttons () == Qt::RightButton)
{
stateLabel->setText (tr("右键按下中间图片"));
}
QMatrix matrix;
matrix.scale (1.8, 1.8);
QImage newImage = Image2.transformed (matrix);
label2->setPixmap (QPixmap::fromImage (newImage));
}
if(event->type () == QEvent::MouseButtonRelease)
{
stateLabel->setText (tr("鼠标释放中间图标"));
label2->setPixmap (QPixmap::fromImage (Image2));
}
}
else if(watched == label3)
{
if(event->type () == QEvent::MouseButtonPress)
{
QMouseEvent *mouseEvent = (QMouseEvent*)event;
if(mouseEvent->buttons () == Qt::LeftButton)
{
stateLabel->setText (tr("左键按下右边图片"));
}
else if(mouseEvent->buttons () == Qt::MidButton)
{
stateLabel->setText (tr("中间按键按下右边图片"));
}
else if(mouseEvent->buttons () == Qt::RightButton)
{
stateLabel->setText (tr("右边按键按下右图标"));
}
QMatrix matrix;
matrix.scale (1.8, 1.8);
QImage newImage = Image3.transformed (matrix);
label3->setPixmap (QPixmap::fromImage (newImage));
}
if(event->type () == QEvent::MouseButtonRelease)
{
stateLabel->setText (tr("鼠标释放右边图片"));
label3->setPixmap (QPixmap::fromImage (Image3));
}
}
}