转载地址:https://www.cnblogs.com/aiguona/p/9999507.html
一、QMouseEvent的详细描述
首先请注意,Qt中的QMouseEvent一般只涉及鼠标左键或右键的单击、释放等操作,而对鼠标滚轮的响应则通过QWheeEvent来处理。
QMouseEvent类包含了用于描述鼠标事件的参数。
当在一个窗口里按住鼠标按键、或移动、或释放就会产生鼠标事件QMouseEvent。
鼠标移动事件只会在按下鼠标按键的情况下才会发生,除非通过显式调用QWidget::setMouseTracking()函数来开启鼠标轨迹,这种情况下只要鼠标指针在移动,就会产生一系列的QT鼠标事件;
在一个窗口中,当鼠标按键被按下时,QT会自动捕捉鼠标轨迹,鼠标指针所在的父窗口会继续接受鼠标事件,直到最后一个鼠标按键被释放。
二、QMouseEvent的传递
一个鼠标事件包含一些指定的接受标志flag用于指出该事件是否会被接收和处理 ,如果鼠标指针所在的父窗口不接收该事件则可以调用函数ignore()予以忽略;
多个重叠的窗口在实现里好比一个递归的倒立树,鼠标事件会沿着鼠标指针所在的父窗口的链表向上传递,直到某个窗口调用accept()函数进行事件处理,否则该事件将被过滤销毁掉;
如果一个鼠标事件传递给鼠标指针所在的窗口,而该窗口的QT::WA_NoMousePropagation位置为TRUE,则该事件不会通过父窗口继续向上传递。
可以通过函数pos()、x()、y()得知鼠标事件发生时鼠标指针相对于窗口的位置。
如果把移动窗口作为一次鼠标事件,可以通过函数globalPos()返回的全局坐标值避免窗口的抖动。
可以使用QWidget::setEndabled()来开启/关闭对应的窗口是否接受键盘和鼠标事件。
需要对鼠标事件进行处理时,通常要重新实现以下几个鼠标事件处理函数:
QWidget::mousePressEvent()
QWidget::mouseReleaseEvent()
QWidget::mouseDoubleClickEvent()
QWidget::mouseMoveEvent()
三、鼠标事件
鼠标事件使用的时候,加头文件
#include
1.鼠标按下事件
复制代码
void Widget::mousePressEvent(QMouseEvent *event)
{
// 如果是鼠标左键按下
if(event->button() == Qt::LeftButton)
{
···
}
// 如果是鼠标右键按下
else if(event->button() == Qt::RightButton)
{
···
}
}
复制代码
2.鼠标移动事件 默认情况下,触发事件需要点击一下,才能触发。可设置为自动触发:setMouseTracking(true);
复制代码
void Widget::mouseMoveEvent(QMouseEvent *event)
{
// 这里必须使用buttons()
if(event->buttons() & Qt::LeftButton) //进行的按位与
{
···
}
}
复制代码
3.鼠标释放事件
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
···
}
4.鼠标双击事件
复制代码
void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{
// 如果是鼠标左键按下
if(event->button() == Qt::LeftButton){
···
}
}
复制代码
5.滚轮事件
复制代码
void Widget::wheelEvent(QWheelEvent *event)
{
if(event->delta() > 0)// 当滚轮远离使用者时
{
···
}
else//当滚轮向使用者方向旋转时
{
···
}
}
复制代码
四、键盘事件
键盘事件使用时,加头文件
#include
1.键盘按下事件
复制代码
void Widget::keyPressEvent(QKeyEvent *event)
{
// 是否按下Ctrl键 特殊按键
if(event->modifiers() == Qt::ControlModifier)
{
// 是否按下M键 普通按键 类似
if(event->key() == Qt::Key_M)
···
}
else
QWidget::keyPressEvent(event); //保存默认事件
//如果是处理两个普通按键,得避免自动重复,释放中也要处理
if(event->key() == Qt::Key_Up)
{
// 按键重复时不做处理
if(event->isAutoRepeat()) return;
// 标记向上方向键已经按下
keyUp = true;
}
else if(event->key() == Qt::Key_Left)
{
if(event->isAutoRepeat()) return;
keyLeft = true;
}
}
复制代码
2.按键释放事件
复制代码
void Widget::keyReleaseEvent(QKeyEvent *event)
{
···
//如果是处理两个普通按键,得避免自动重复
if(event->key() == Qt::Key_Up)
{
if(event->isAutoRepeat()) return;
···
}
else if(event->key() == Qt::Key_Left)
{
if(event->isAutoRepeat()) return;
···
}
}
复制代码
五、常用公有成员函数
1.globalPos()、globalX()、globalY()这三个函数返回的是鼠标指针的全局坐标。
const QPoint & QMouseEvent::globalPos () const
返回鼠标指针的全局坐标值,对于异步窗口系统例如X11这是一个很重要的特性,无论何时移动窗口作为对鼠标事件的响应时,globalPos()返回的当前鼠标指针坐标值和QCursor::pos()的返回值是有区别的,可以通过调用QWidget::mapToGlobal(pos())在窗口坐标和全局坐标系之间进行转换。
int QMouseEvent::globalX () const
返回鼠标事件发生时鼠标指针全局坐标的X值,相当于globalPos.x();
int QMouseEvent::globalY () const
返回鼠标事件发生时鼠标指针全局坐标的Y值,相当于globalPos.y()。
2.pos()、posF()、x()、y()这四个函数返回的是鼠标指针在当前接收鼠标事件的窗口中的位置。
const QPoint & QMouseEvent::pos () const
返回鼠标指针和接受该鼠标事件窗口的相对位置,其中的坐标值为整型;
QPointF QMouseEvent::posF () const
返回鼠标指针在接受该鼠标事件窗口的相对位置,该坐标值用float类型表示可以增加精确度;
int QMouseEvent::x () const
返回鼠标事件发生时,鼠标指针在当前接收鼠标事件的窗口中位置的x坐标值,相当与pos().x();
int QMouseEvent::y () const
返回鼠标事件发生时,鼠标指针在当前接收鼠标事件的窗口中位置的y坐标值,相当于pos().y()。
拖拽事件:
例如拖拽QTreeview里的item需要传递给QTableView时需要重写模型中的函数:
//让模型具有拖拽放下的功能
Qt::ItemFlags TreeComponent::flags(const QModelIndex &index) const
{
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
flags = flags | Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled;
return flags;
}
//拖拽并把数据保存下来
QMimeData *TreeComponent::mimeData(const QModelIndexList &indexes) const
{
if (indexes.count() <= 0)
return 0;
QMimeData *data = new QMimeData;
qDebug()<setData("drag","鼠标拖拽");
//这种形式会报错,不知为何
//data->setData("name",item(indexes.at(0).row(),0)->text().toLocal8Bit());
data->setData("name",indexes.at(0).data().toString().toLocal8Bit());
data->setData("score",indexes.at(1).data().toString().toLocal8Bit());
return data;
}
//把剪切板中数据粘上去,此函数最后一个参数可以知道所放的位置
bool TreeComponent::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
QString st=QString::fromLocal8Bit(data->data(“name”));
QString st1=QString::fromLocal8Bit(data->data(“score”));
this->setItem(parent.row(),parent.column(),new QStandardItem(st));
// this->setItem(m_rowCount,1,new QStandardItem(st1));
m_rowCount++;
}
QStringList TreeComponent::mimeTypes() const
{
QStringList types;
types << “drag”;
return types;
}
例如拖拽QTreeview里的item需要传递给QWidget时需要重写QWidget:
void WidgetPicture::dragLeaveEvent(QDragLeaveEvent *event)
{
qDebug() << “dragLeaveEvent”;
}
void WidgetPicture::dragMoveEvent(QDragMoveEvent *event)
{
QStringList formats = event->mimeData()->formats();
qDebug() << "dragMoveEvent formats = " << formats;
event->setDropAction(Qt::MoveAction);
event->accept();
}
void WidgetPicture::dropEvent(QDropEvent *event)
{
QStringList formats = event->mimeData()->formats();
qDebug() << "dropEvent formats = " << formats;
if (event->mimeData()->hasFormat(“name”))
{
QVariant varData = event->mimeData()->data(“name”);
QByteArray byteData = varData.toByteArray();
QString tmpQStr = byteData;
qDebug()<> (node);
stream>>ip;
// TreeNode* devNode = (TreeNode*)(node);
// if (devNode)
// ui.lineEdit->setText(devNode->mText);
//此语句是删掉原来的item
// event->setDropAction(Qt::MoveAction);
event->accept();
}
else
{
event->ignore();
}
}
void WidgetPicture::dragEnterEvent(QDragEnterEvent *event)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
如果是向QWidget画画面则需要重写:
void WidgetPicture::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setBrush(Qt::white);
painter.drawRect(0, 0, this->width(), this->height()); //先画成白色
if (image.size().width() <= 0) return;
///将图像按比例缩放成和窗口一样大小
QImage img = image.scaled(this->size(),Qt::KeepAspectRatio);
int x = this->width() - img.width();
int y = this->height() - img.height();
x /= 2;
y /= 2;
painter.drawImage(QPoint(x,y),img); //画出图像
}
调用update()触发