本次使用了QGraphicsView来加载图像,然后给其设置了一个QGraphicsScene场景,再给场景添加了一个自定义的QGraphicsItem,在其中重写了paint事件,用来重绘图像。
正常情况时,QGraphicsItem上图像的有效区域QRect大小和QGraphicsView一致,此时正好铺满,鼠标位置的坐标可以比较轻松的推算出其在图像有效区域的全局坐标。
当个人碰到的某些时候,QGraphicsItem上图像的有效区域QRect大小并不和QGraphicsView一致,比如宽度留白了,即左右两边有空缺。此时发现如果用正常的方法去获取鼠标位置坐标在图像有效区域的全局坐标,会得到不准确的坐标。明明是鼠标在图像的顶点,却可能x坐标或y坐标不从0开始。
针对这种情况,使用以下几句可以得到鼠标位置在图像有效区域的全局坐标。
class ImgShow : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
ImgShow(QRectF rect);
~ImgShow() override;
void UpdateImageRect(QRectF rect);
void UpdateImageShow(QPixmap pix);
protected:
virtual QRectF boundingRect() const override;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void hoverMoveEvent(QGraphicsSceneHoverEvent* event);
private:
QRectF curRect;
QPixmap curPix;
QMutex mtx;
};
cpp
ImgShow::ImgShow(QRectF rect)
{
curRect = rect;
//使其在鼠标未点击也能响应悬停事件
setAcceptHoverEvents(true);
}
ImgShow::~ImgShow()
{
}
void ImgShow::UpdateImageRect(QRectF rect)
{
mtx.lock();
curRect = rect;
mtx.unlock();
}
void ImgShow::UpdateImageShow(QPixmap pix)
{
mtx.lock();
curPix = pix;
mtx.unlock();
// 设置玩图像数据后刷新图像
QGraphicsView * view = this->scene()->views().at(0);
view->viewport()->update();
}
QRectF ImgShow::boundingRect() const
{
return curRect;
}
void ImgShow::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
mtx.lock();
// painter->drawPixmap(-static_cast<int>(curRect.width() / 2), -static_cast<int>(curRect.height() / 2), curPix);
//上面的drawPixmap起始位置不太一样
painter->drawPixmap(curRect.toRect(), curPix);
qDebug()<< curRect.width() << curRect.height();
mtx.unlock();
}
void ImgShow::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
{
QPointF localPos = event->pos(); // 当前鼠标位置相对于图元坐标系的坐标
QRectF imageRect = mapRectToScene(boundingRect()); // 图像有效区域在场景中的位置
QPointF globalPos = scenePos() + localPos - imageRect.topLeft(); // 转换为图像有效区域的全局坐标
qDebug()<< globalPos;
}
//scenePos()为图元在场景的坐标,因此 scenePos() + localPos 为鼠标在场景坐标系的坐标
//imageRect.topLeft()为图像有效区域的左上角在图元坐标系的位置,因此 localPos - imageRect.topLeft() 为当前鼠标事件在图片局部坐标系中的位置
当图像的有效区域并不是铺满图元时,就可以用该方式得到,当前鼠标位置对于图像有效区域的全局坐标