【[Qt]基于QGraphicsView的图像显示控件,支持放大、缩小、鼠标拖动】

这篇具有很好参考价值的文章主要介绍了【[Qt]基于QGraphicsView的图像显示控件,支持放大、缩小、鼠标拖动】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

这是一个Qt平台的基于QGraphicsView类的图像显示控件,支持输入QPixmap、QImage、opencv的从cv::Mat类。
实现平台:Windows 10 x64 + Qt 6.2.3 + MSVC 2019 + opencv 4.5

先来看演示视频

【[Qt]基于QGraphicsView的图像显示控件,支持放大、缩小、鼠标拖动】

控件类实现

ImageViewer.h文件

#ifndef IMAGEVIEWER_H
#define IMAGEVIEWER_H

#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsView>
#include <QMouseEvent>
#include <QImage>
#include <QWheelEvent>
#include <QGraphicsScene>
#include "opencv2/opencv.hpp"

class ImageViewer : public QGraphicsView
{
    Q_OBJECT
public:
    explicit ImageViewer(QWidget *parent = nullptr);

signals:


public:
    void setQImage(QImage);
    void setMatImage(cv::Mat );
    void setPixmap(QPixmap);
    void resetImage();
    QImage getQImage();
    cv::Mat getMatImage();
    QPixmap getPixmap();

protected:
    virtual void wheelEvent(QWheelEvent *event) override;
    virtual void keyPressEvent(QKeyEvent *event) override;
    virtual void mousePressEvent(QMouseEvent *event) override;
    virtual void mouseMoveEvent(QMouseEvent *event) override;
    virtual void mouseReleaseEvent(QMouseEvent *event) override;
    void zoom(QPoint factor);
    void togglePan(bool pan, const QPoint &startPos = QPoint());
    void pan(const QPoint &panTo);
    void initShow();

private:
    QPixmap m_image;
    bool m_isPan;
    QPoint m_prevPan;
    QGraphicsScene *scene;

};

#endif // IMAGEVIEWER_H

ImageViewer.cpp 文件

#include "imageviewer.h"
#include <QScrollBar>

ImageViewer::ImageViewer(QWidget *parent)
    : QGraphicsView{parent},
    m_isPan(false),
    m_prevPan(0,0),
    scene(nullptr)
{
    scene = new QGraphicsScene(this);
    this->setScene(scene);

    setDragMode(QGraphicsView::DragMode::NoDrag);
    setInteractive(false);
    setEnabled(false);
}
QImage cvMatToQImage(cv::Mat &src)
{
    if(src.channels() == 1) { // if grayscale image
        return QImage((uchar*)src.data, src.cols, src.rows, static_cast<int>(src.step), QImage::Format_Grayscale8).copy();
    }
    if(src.channels() == 3) { // if 3 channel color image
        cv::Mat rgbMat;
        cv::cvtColor(src, rgbMat, cv::COLOR_BGR2RGB); // invert BGR to RGB
        return QImage((uchar*)rgbMat.data, src.cols, src.rows, static_cast<int>(src.step), QImage::Format_RGB888).copy();
    }
    return QImage();
}

//将QImage转化为Mat
cv::Mat qImageToCvMat( const QImage &inImage)
{
    switch (inImage.format())
    {
    case QImage::Format_RGB32:
    case QImage::Format_RGB888:
    {

        QImage   swapped = inImage;
        if ( inImage.format() == QImage::Format_RGB32 )
        {
            swapped = swapped.convertToFormat( QImage::Format_RGB888 );
        }
        cv::Mat matImg = cv::Mat(swapped.height(), swapped.width(),
                                  CV_8UC3,
                                  const_cast<uchar*>(swapped.bits()),
                                  static_cast<size_t>(swapped.bytesPerLine())
                                  );
        cv::cvtColor(matImg,matImg,cv::COLOR_RGB2BGR);
        return matImg.clone();
    }
    case QImage::Format_Indexed8:
    {
        cv::Mat  mat( inImage.height(), inImage.width(),
                      CV_8UC1,
                      const_cast<uchar*>(inImage.bits()),
                      static_cast<size_t>(inImage.bytesPerLine())
                      );
        return mat.clone();
    }
    default:
        break;
    }
    return cv::Mat();
}

void ImageViewer::setQImage(QImage image)
{   if(image.isNull())
        return;
    m_image = QPixmap::fromImage(image);
    initShow();
}
void ImageViewer::setMatImage(cv::Mat src)
{
    if(src.empty())
        return;
    m_image = QPixmap::fromImage(cvMatToQImage(src));
    initShow();
}
void ImageViewer::setPixmap(QPixmap pixmap)
{
    m_image = pixmap.copy();
    initShow();
}
void ImageViewer::resetImage()
{
    if(m_image.isNull())
        return;
    scene->clear();
    setEnabled(false);
}
QImage  ImageViewer::getQImage()
{
    return m_image.toImage();
}
cv::Mat ImageViewer::getMatImage()
{
    return qImageToCvMat(m_image.toImage());
}
QPixmap ImageViewer::getPixmap()
{
    return m_image;
}
void ImageViewer::initShow()
{
    setEnabled(true);
    setMouseTracking(true);
    scene->clear();
    scene->addPixmap(m_image);
    scene->update();
    this->resetTransform();
    this->setSceneRect(m_image.rect());
    this->fitInView(QRect(0, 0, m_image.width(), m_image.height()), Qt::KeepAspectRatio);
}
void ImageViewer::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton){
        togglePan(true, event->pos());
        event->accept();
        return;
    }
    event->ignore();
}

void ImageViewer::mouseMoveEvent(QMouseEvent *event)
{
    if(m_isPan) {
        pan(event->pos());
        event->accept();
        return;
    }
    event->ignore();
}


void ImageViewer::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton){
        togglePan(false);
        event->accept();
        return;
    }
    event->ignore();
}

void ImageViewer::zoom(QPoint factor)
{
    QRectF FOV = this->mapToScene(this->rect()).boundingRect();
    QRectF FOVImage = QRectF(FOV.left(), FOV.top(), FOV.width(), FOV.height());
    float scaleX = static_cast<float>(m_image.width()) / FOVImage.width();
    float scaleY = static_cast<float>(m_image.height()) / FOVImage.height();
    float minScale = scaleX > scaleY ? scaleY : scaleX;
    float maxScale = scaleX > scaleY ? scaleX : scaleY;
    if ((factor.y() > 0 && minScale > 100) || (factor.y() < 0 && maxScale < 1 )) {
      return;
    }
    if(factor.y()>0)
        scale(1.2, 1.2);
    else
        scale(0.8, 0.8);
}
void ImageViewer::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_O) {
        this->resetTransform();
        this->setSceneRect(m_image.rect());
        this->fitInView(QRect(0, 0, m_image.width(), m_image.height()), Qt::KeepAspectRatio);
    }
}

void ImageViewer::pan(const QPoint &panTo)
{
    auto hBar = horizontalScrollBar();
    auto vBar = verticalScrollBar();
    auto delta = panTo - m_prevPan;
    m_prevPan = panTo;
    hBar->setValue(hBar->value() - delta.x());
    vBar->setValue(vBar->value() - delta.y());
}

void ImageViewer::wheelEvent(QWheelEvent *event)
{
    if(m_image.isNull())
        return;
    QPoint numDegrees = event->angleDelta() / 8;
    if (!numDegrees.isNull()) {
        QPoint numSteps = numDegrees / 15;
        zoom(numSteps);
    }
    event->accept();
}


void ImageViewer::togglePan(bool pan, const QPoint &startPos)
{
    if(pan){
        if(m_isPan) {
            return;
        }
        m_isPan = true;
        m_prevPan = startPos;
        setCursor(Qt::ClosedHandCursor);
    } else {
        if(!m_isPan) {
            return;
        }
        m_isPan = false;
        m_prevPan = QPoint(0,0);
        setCursor(Qt::ArrowCursor);
    }
}

控件类的使用

具体使用代码如下
1、初始化类对象,并加入界面布局中

	//初始化图片浏览控件,并添加到布局
  	m_view = new ImageViewer(this);
   	//在界面的一个布局中加入控件
   	ui->horizontalLayout_3->addWidget(m_view);

2、打开图像,并加载到控件中

QString filename = getFilePath(QDir::currentPath(),this);
    qDebug() << filename;
    if(filename == "")
        return;
    //读取为QPixmap
    QPixmap mapImg(filename);
    m_view->setPixmap(mapImg);

    //读取为QImage
//    QImage img(filename);
//    m_view->setQImage(img);

    //读取为cv::Mat
//    cv::Mat matImg = cv::imread(filename.toLocal8Bit().data(),cv::IMREAD_UNCHANGED);
//    m_view->setMatImage(matImg);

3、从控件中卸载图片

m_view->resetImage();

如果还是看不懂、建议直接下载源代码

源码链接:https://download.csdn.net/download/xiaohuihuihuige/87239431
百度云:
链接:https://pan.baidu.com/s/1W-KUlIKUFAktUKFin63N0g
提取码:4g8a文章来源地址https://www.toymoban.com/news/detail-502511.html

到了这里,关于【[Qt]基于QGraphicsView的图像显示控件,支持放大、缩小、鼠标拖动】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Matlab上位机——串口收发、接收转为图像实时显示、图像放大缩小等功能

    原例程代码可以进行串口接收发送,加载与存储数据 本人在例程代码的基础上添加了共三个功能 1.加载文件数据,三通道同时显示波形 2.放大缩小 3.均值滤波 4.将接收到的数据以固定位数转换为实时波形 布局 加载文件数据后(excel的csv格式) 滤波效果 实时波形采集当时忘了

    2024年02月02日
    浏览(38)
  • vue3 - 实现图片放大缩小和拖曳拖动功能,鼠标移入图像可拖曳移动,鼠标移入图像时滚轮放大缩小功能(vue3网页项目让图片支持鼠标拖动和滚轮放大缩小详细教程,提供完整示例源码,一键复制开箱即用!)

    在 vue3 网站项目中,详细实现图片拖曳拖动、缩小放大功能,鼠标移入图片时可滚轮放大缩小和拖拽图像功能示例, 直接复制全部代码,运行后简单修改即可使用。 以下就是示例图的完整代码,可复制运行。

    2024年02月03日
    浏览(43)
  • 【[Qt]基于QChartView开发的图表显示控件,支持实时显示,动态更新,支持鼠标交互等操作】

    十字线和显示坐标实现 在.h文件中定义十字线lineitem变量和坐标textitem变量 在Cpp文件中初始化 然后定义鼠标事件,在鼠标进入时显示,移出时隐藏,移动时显示。 其他实现请参考具体代码 ChartDrawer.h文件 ChartDrawer.cpp 文件 具体使用代码如下 1、初始化类对象,并加入界面布局

    2023年04月23日
    浏览(31)
  • Stable Diffusion 无损放大图像和缩小图像

    Stable Diffusion默认生成的图片尺寸为512×512,这种尺寸的分辨率可能无法满足高质量的要求。若想生成大图,存在两种可选的方法,在显卡足够支撑的情况下可以将图像当打到8K。 在生成图片时,可选择使用 hires.fix 高分辨率修复功能,该功能会将生成图片的尺寸从512×512调整至

    2024年02月12日
    浏览(38)
  • opencv 图像的缩放(放大,缩小),翻转,旋转

    opencv 图像的缩放(放大,缩小),翻转,旋转 opencv 最常用的图像缩放方法是使用 cv2::resize() 函数,它需要指定输出图像的大小,和插值算法; opencv 最常用的图像翻转方法是使用 cv::flip() 函数,它需要指定图像翻转方式; opencv 最常用的图像旋转方法是使用 cv::warpAffine() 函数,

    2024年02月07日
    浏览(41)
  • uniapp图片放大缩小预览,并支持图片拖动附效果图

    效果图: 放大缩小和拖动是根据 movable-area 组件来实现的,小程序和uniapp都支持这个组件。 movable-area | 微信开放文档 微信开发者平台文档 https://developers.weixin.qq.com/miniprogram/dev/component/movable-area.html 实现思路: 默认显示默认大小的图片,点击图片执行yulan事件从而显示放大缩

    2024年02月11日
    浏览(29)
  • Openlayers实战:自定义放大缩小,显示zoom等级

    Openlayers地图中,默认的zoom组件是在左上角,这个组件很重要,方便大家来操控地图。在实际项目中,大家往往要改写这个组件,通常会放置到右下角,方便鼠标操作。 在我们的实战课程里,自定义了放大缩小,并增加了显示zoom等级的功能,实际的项目中往往都是这样办理的

    2024年02月13日
    浏览(52)
  • Qt for python QChartView鼠标滚动放大缩小

    最近使用Qt for python 做了一个图表,有个需求是用鼠标中轮,根据中轮的滚动来放大缩小显示的曲线,我这边用Qml实现的QChart图表, 当然QWidget的相应方法也会提到,都是一样的,相对于qml实现这个功能是真麻烦,得使用C++才能实现,而我又是使用的python,所以难度更大,正好

    2024年02月09日
    浏览(26)
  • 【Qt+FFmpeg】鼠标滚轮放大、缩小、移动——解码播放本地视频(三)

     上一期我们实现了播放、暂停、重播、倍速功能,这期来谈谈如何实现鼠标滚轮放大缩小和移动;如果还没看过上期,请移步 【Qt+FFmpeg】解码播放本地视频(一)_logani的博客-CSDN博客【Qt+FFmpeg】解码播放本地视频(二)——实现播放、暂停、重播、倍速功能_logani的博客-C

    2024年02月10日
    浏览(29)
  • 【精选】使用opencv的resize函数进行等比例放大或缩小图像

    在 OpenCV 中,使用 resize() 函数可以对图像进行缩放操作。若要按比例扩大或缩小图像,可以通过指定目标大小,并结合原始图像的尺寸进行等比例扩大。 以下是一个示例代码,展示了如何在 Python 中使用 OpenCV 对图像进行等比例扩大: 这段代码首先读取原始图像,然后获取其

    2024年02月03日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包