15、Qt显示图片并支持缩放、移动等操作

本文介绍了如何在Qt中创建一个自定义C++类PhotoLabel,该类扩展自QLabel,用于显示图片并支持右键菜单、缩放和移动功能。详细步骤包括创建项目、添加自定义类、设置图片和处理用户交互事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、新建项目

点击“New Project”,选择“Application”“Qt Widget Application”,点击“Choose”

更改项目名称和位置

选择编译器

默认

默认

二、创建自定义类

右击项目名,选择“Add New”

选择“C++” -> "C++ Class",点击“Choose”

更改名称和基类

默认

更改photolabel.h的代码

#ifndef PHOTOLABEL_H
#define PHOTOLABEL_H

#include <QObject>
#include <QLabel>
#include <QMenu>

class PhotoLabel : public QLabel
{
public:
    explicit PhotoLabel(QWidget *parent = nullptr);

    void setPhoto(QString);  //设置图片

    void clearShow();   //清空显示

protected:
    void contextMenuEvent(QContextMenuEvent *event) override;   //右键菜单
    void paintEvent(QPaintEvent *event);                        //QPaint画图
    void wheelEvent(QWheelEvent *event) override;               //鼠标滚轮滚动
    void mousePressEvent(QMouseEvent *event) override;          //鼠标摁下
    void mouseMoveEvent(QMouseEvent *event) override;           //鼠标松开
    void mouseReleaseEvent(QMouseEvent *event) override;        //鼠标发射事件

private slots:
    void initWidget();      //初始化
    void onSelectImage();   //选择打开图片
    void onZoomInImage();   //图片放大
    void onZoomOutImage();  //图片缩小
    void onPresetImage();   //图片还原

private:
    QImage m_image;           //显示的图片
    qreal m_zoomValue = 1.0;  //鼠标缩放值
    int m_xPtInterval = 0;    //平移X轴的值
    int m_yPtInterval = 0;    //平移Y轴的值
    QPoint m_oldPos;          //旧的鼠标位置
    bool m_pressed = false;   //鼠标是否被摁压
    QString m_localFileName;  //文件名称
    QMenu *m_menu;            //右键菜单
};

#endif // PHOTOLABEL_H

更改photolabel.cpp的代码

#include "photolabel.h"
#include <QPainter>
#include <QDebug>
#include <QWheelEvent>
#include <QFileDialog>

PhotoLabel::PhotoLabel(QWidget *parent):QLabel(parent)
{
    initWidget();
}

/**
* @brief PhotoLabel::initWidget 初始化
*/
void PhotoLabel::initWidget()
{
    //初始化右键菜单
    m_menu = new QMenu(this);
    QAction *loadImage = new QAction;
    loadImage->setText("选择图片");
    connect(loadImage, &QAction::triggered, this, &PhotoLabel::onSelectImage);
    m_menu->addAction(loadImage);
    m_menu->addSeparator();

    QAction *zoomInAction = new QAction;
    zoomInAction->setText("放大");
    connect(zoomInAction, &QAction::triggered, this, &PhotoLabel::onZoomInImage);
    m_menu->addAction(zoomInAction);

    QAction *zoomOutAction = new QAction;
    zoomOutAction->setText("缩小");
    connect(zoomOutAction, &QAction::triggered, this, &PhotoLabel::onZoomOutImage);
    m_menu->addAction(zoomOutAction);

    QAction *presetAction = new QAction;
    presetAction->setText("还原");
    connect(presetAction, &QAction::triggered, this, &PhotoLabel::onPresetImage);
    m_menu->addAction(presetAction);
    m_menu->addSeparator();

    QAction *clearAction = new QAction;
    clearAction->setText("清空");
    connect(clearAction, &QAction::triggered, this, &PhotoLabel::clearShow);
    m_menu->addAction(clearAction);
}

/**
* @brief PhotoLabel::setPhoto 设置要显示的图片
* @param path 图片路径
*/
void PhotoLabel::setPhoto(QString path)
{
    if(path.isEmpty())
    {
        return;
    }

    m_zoomValue = 1.0;
    m_xPtInterval = 0;
    m_yPtInterval = 0;

    m_localFileName = path;
    m_image.load(m_localFileName);
    update();
}

/**
* @brief PhotoLabel::clearShow 清空
*/
void PhotoLabel::clearShow()
{
    m_localFileName = "";
    m_image = QImage();
    this->clear();
}

/**
* @brief PhotoLabel::paintEvent 绘图事件
* @param event
*/
void PhotoLabel::paintEvent(QPaintEvent *event)
{
    if(m_image.isNull())
        return QWidget::paintEvent(event);

    QPainter painter(this);

    // 根据窗口计算应该显示的图片的大小
    int width = qMin(m_image.width(), this->width());
    int height = int(width * 1.0 / (m_image.width() * 1.0 / m_image.height()));
    height = qMin(height, this->height());
    width = int(height * 1.0 * (m_image.width() * 1.0 / m_image.height()));

    // 平移
    painter.translate(this->width() / 2 + m_xPtInterval, this->height() / 2 + m_yPtInterval);

    // 缩放
    painter.scale(m_zoomValue, m_zoomValue);

    // 绘制图像
    QRect picRect(-width / 2, -height / 2, width, height);
    painter.drawImage(picRect, m_image);

    QWidget::paintEvent(event);
}

/**
* @brief PhotoLabel::wheelEvent 滚轮滚动缩放图片
* @param event
*/
void PhotoLabel::wheelEvent(QWheelEvent *event)
{
    int value = event->delta();
    if (value > 0)  //放大
        onZoomInImage();
    else            //缩小
        onZoomOutImage();

    update();
}

/**
* @brief PhotoLabel::mousePressEvent 鼠标按下,为移动图片做准备
* @param event
*/
void PhotoLabel::mousePressEvent(QMouseEvent *event)
{
    m_oldPos = event->pos();
    m_pressed = true;
    this->setCursor(Qt::ClosedHandCursor); //设置鼠标样式
}

/**
* @brief PhotoLabel::mouseMoveEvent 鼠标按下后,再移动鼠标,图片随之移动
* @param event
*/
void PhotoLabel::mouseMoveEvent(QMouseEvent *event)
{
    if (!m_pressed)
        return QWidget::mouseMoveEvent(event);

    QPoint pos = event->pos();
    int xPtInterval = pos.x() - m_oldPos.x();
    int yPtInterval = pos.y() - m_oldPos.y();

    m_xPtInterval += xPtInterval;
    m_yPtInterval += yPtInterval;

    m_oldPos = pos;
    update();
}

/**
* @brief PhotoLabel::mouseReleaseEvent 鼠标抬起,图片移动结束
*/
void PhotoLabel::mouseReleaseEvent(QMouseEvent */*event*/)
{
    m_pressed = false;
    this->setCursor(Qt::ArrowCursor); //设置鼠标样式
}

/**
* @brief PhotoLabel::contextMenuEvent 右键显示菜单栏
* @param event
*/
void PhotoLabel::contextMenuEvent(QContextMenuEvent *event)
{
    QPoint pos = event->pos();
    pos = this->mapToGlobal(pos);
    m_menu->exec(pos);
}

/**
* @brief PhotoLabel::onSelectImage 选择图片
*/
void PhotoLabel::onSelectImage()
{
    QString path = QFileDialog::getOpenFileName(this, "选择 要显示的图片", "./", tr("Images (*.png *.jpg *.jpeg)"));
    if (path.isEmpty())
        return;

    setPhoto(path);
}

/**
* @brief PhotoLabel::onZoomInImage 图片放大
*/
void PhotoLabel::onZoomInImage()
{
    m_zoomValue += 0.05;
    update();
}

/**
* @brief PhotoLabel::onZoomOutImage 图片缩小
*/
void PhotoLabel::onZoomOutImage()
{
    m_zoomValue -= 0.05;
    if (m_zoomValue <= 0)
    {
        m_zoomValue = 0.05;
        return;
    }

    update();
}

/**
* @brief PhotoLabel::onPresetImage 图片还原
*/
void PhotoLabel::onPresetImage()
{
    m_zoomValue = 1.0;
    m_xPtInterval = 0;
    m_yPtInterval = 0;
    update();
}

三、自定义类的使用

双击“mainwindow.ui”

拖拽一个Label,并进行网格布局

右击TextLabel,选择“提升为”

 输入类名称,点击“添加”

点击“提升” 

label的基类被更改

四、运行测试

右击界面,选择“选择图片”

添加一张图片之后,可以右击选择“放大/缩小/还原”等,也可以鼠标滚轮控制缩放;

也可以鼠标点击不松开,移动鼠标,从而使图片移

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值