Qt QGraphicsItem获取鼠标位置对应图像坐标

本次使用了QGraphicsView来加载图像,然后给其设置了一个QGraphicsScene场景,再给场景添加了一个自定义的QGraphicsItem,在其中重写了paint事件,用来重绘图像。

正常情况时,QGraphicsItem上图像的有效区域QRect大小和QGraphicsView一致,此时正好铺满,鼠标位置的坐标可以比较轻松的推算出其在图像有效区域的全局坐标。
当个人碰到的某些时候,QGraphicsItem上图像的有效区域QRect大小并不和QGraphicsView一致,比如宽度留白了,即左右两边有空缺。此时发现如果用正常的方法去获取鼠标位置坐标在图像有效区域的全局坐标,会得到不准确的坐标。明明是鼠标在图像的顶点,却可能x坐标或y坐标不从0开始。

针对这种情况,使用以下几句可以得到鼠标位置在图像有效区域的全局坐标。

cpp 复制代码
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

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() 为当前鼠标事件在图片局部坐标系中的位置

当图像的有效区域并不是铺满图元时,就可以用该方式得到,当前鼠标位置对于图像有效区域的全局坐标

相关推荐
lsjweiyi31 分钟前
极简AI工具箱网站开源啦!
opencv·开源·微信支付·支付宝支付·百度ai·极简ai工具箱·ai图像处理
一路冰雨4 小时前
Qt打开文件对话框选择文件之后弹出两次
开发语言·qt
Jack黄从零学c++4 小时前
opencv(c++)---自带的卷积运算filter2D以及应用
c++·人工智能·opencv
老赵的博客5 小时前
QT 自定义界面布局要诀
开发语言·qt
码码哈哈0.05 小时前
VSCode 2022 离线安装插件QT VSTOOl报错此扩展不能安装在任何当前安装的产品上。
ide·vscode·qt
饭碗、碗碗香9 小时前
OpenCV笔记:图像去噪对比
人工智能·笔记·opencv·计算机视觉
feiyangqingyun9 小时前
Qt/C++离线地图的加载和交互/可以离线使用/百度和天地图离线/支持手机上运行
c++·qt·qt天地图·qt离线地图·qt地图导航
是Dream呀21 小时前
Python从0到100(七十三):Python OpenCV-OpenCV实现手势虚拟拖拽
开发语言·python·opencv
gz94561 天前
windows下,用CMake编译qt项目,出现错误By not providing “FindQt5.cmake“...
开发语言·qt
「QT(C++)开发工程师」1 天前
Ubuntu 26.04 LTS 大升级:Qt 6 成为未来新引擎
qt