Qt图像裁剪实时显示尺寸实现

鼠标按着红线左右拖动,红框中实时体现左右侧拖动了多少像素,红线之间剩余多少

cpp 复制代码
#include "myqgraphicsview.h"

MyQGraphicsView::MyQGraphicsView(QWidget *parent) : QGraphicsView(parent)
{
    m_graphics_scene = new QGraphicsScene(this);
    setScene(m_graphics_scene);

    // 设置视图属性
    setRenderHint(QPainter::Antialiasing);
    setDragMode(QGraphicsView::NoDrag);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    // 初始化裁剪线
    m_graphics_line_item_left = m_graphics_scene->addLine(0, 0, 0, 1, QPen(Qt::red, 2));
    m_graphics_line_item_right = m_graphics_scene->addLine(1, 0, 1, 1, QPen(Qt::red, 2));

    // 初始化尺寸标签
    m_size_label = new QLabel(this);
    //m_size_label->setStyleSheet("QLabel { background-color : white; color : black; }");
    m_size_label->setAlignment(Qt::AlignCenter);
    m_size_label->hide();

    // 默认不显示任何线
    m_graphics_line_item_left->hide();
    m_graphics_line_item_right->hide();
}
void MyQGraphicsView::set_image(const QPixmap &pixmap)
{
    if(m_is_first_load_image)
    {
        m_is_first_load_image =false;

        m_graphics_scene->clear();
        m_graphics_pixmap_item = m_graphics_scene->addPixmap(pixmap);
        m_graphics_scene->setSceneRect(pixmap.rect());

        // 重新初始化裁剪线
        m_graphics_line_item_left = m_graphics_scene->addLine(0, 0, 0, pixmap.height(), QPen(Qt::red, 10));
        m_graphics_line_item_right = m_graphics_scene->addLine(pixmap.width(), 0, pixmap.width(), pixmap.height(), QPen(Qt::red, 10));

        // 显示线
        m_graphics_line_item_left->show();
        m_graphics_line_item_right->show();

        m_pure_image_width = pixmap.width();
        // 设置初始裁剪区域为整个图像
        m_crop_rect = pixmap.rect();
        update_size_label();
    }
    else
    {
        delete m_graphics_pixmap_item; m_graphics_pixmap_item =nullptr;
        m_graphics_pixmap_item = m_graphics_scene->addPixmap(pixmap);

        m_graphics_line_item_left->show();
        m_graphics_line_item_right->show();
    }
}

QRect MyQGraphicsView::get_crop_rect()const{return m_crop_rect;}

void MyQGraphicsView::mousePressEvent(QMouseEvent *event)
{
    QPointF scenePos = mapToScene(event->pos());
    // 检查是否点击了左线或右线
    if (m_graphics_line_item_left->contains(scenePos))
    {
        m_dragging_left = true;
    }
    else if (m_graphics_line_item_right->contains(scenePos))
    {
        m_dragging_right = true;
    }

    QGraphicsView::mousePressEvent(event);
}

void MyQGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
    if (m_dragging_left || m_dragging_right)
    {
        QPointF scenePos = mapToScene(event->pos());
        int x = qBound(0.0, scenePos.x(), m_graphics_scene->width());

        if (m_dragging_left) // 左线不能超过右线
        {
            x = qMin(x, (int)m_graphics_line_item_right->line().x1() - 1);
            m_graphics_line_item_left->setLine(x, 0, x, m_graphics_scene->height());
        }
        else if (m_dragging_right) // 右线不能超过左线
        {
            x = qMax(x, (int)m_graphics_line_item_left->line().x1() + 1);
            m_graphics_line_item_right->setLine(x, 0, x, m_graphics_scene->height());
        }

        // 更新裁剪矩形
        m_crop_rect.setLeft(m_graphics_line_item_left->line().x1());
        m_crop_rect.setRight(m_graphics_line_item_right->line().x1());
        m_crop_rect.setTop(0);
        m_crop_rect.setBottom(m_graphics_scene->height());

        update_size_label();
        emit cropSizeChanged(m_crop_rect.width(), m_crop_rect.height());
        emit signal_left_right(m_crop_rect.x(), m_pure_image_width - m_crop_rect.x() - m_crop_rect.width());
    }
    QGraphicsView::mouseMoveEvent(event);
}
void MyQGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
    m_dragging_left = false;
    m_dragging_right = false;
    QGraphicsView::mouseReleaseEvent(event);
}
void MyQGraphicsView::resizeEvent(QResizeEvent *event)
{
    QGraphicsView::resizeEvent(event);
    fitInView(m_graphics_scene->sceneRect(), Qt::KeepAspectRatio);
    update_size_label_position();
}
void MyQGraphicsView::update_size_label()
{
    int width = m_crop_rect.width();
    int height = m_crop_rect.height();
    m_size_label->setText(QString("left=%0 [%1 x %2] right=%3").arg(m_crop_rect.x()).arg(width).arg(height).arg(m_pure_image_width - m_crop_rect.x()- m_crop_rect.width()));
    m_size_label->adjustSize();
    update_size_label_position();
    m_size_label->show();
}
void MyQGraphicsView::update_size_label_position()
{
    QRectF rect = mapFromScene(m_crop_rect).boundingRect();
    m_size_label->move(rect.center().x() - m_size_label->width()/2,rect.top() - m_size_label->height() - 5);
}
cpp 复制代码
#ifndef MYQGRAPHICSVIEW_H
#define MYQGRAPHICSVIEW_H

#include <QThread>
#include <QObject>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QGraphicsRectItem>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QPen>
#include <QGraphicsLineItem>
#include <QMouseEvent>

class MyQGraphicsView : public QGraphicsView
{
    Q_OBJECT
public:
    explicit MyQGraphicsView(QWidget *parent = nullptr);
    void set_image(const QPixmap &pixmap);
    QRect get_crop_rect() const;

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;

private:
    void update_size_label();
    void update_size_label_position();

signals:
    void cropSizeChanged(int width, int height);
    /**
     * @brief signal_left_right
     * @param left: 原图左侧被裁剪了N个像素
     * @param right: 原图右侧被裁剪了N个像素
     */
    void signal_left_right(int left, int right);

private:
    QGraphicsScene *m_graphics_scene = nullptr;                     //创建一个图像视场
    QGraphicsPixmapItem *m_graphics_pixmap_item = nullptr;          //图像对象
    QGraphicsLineItem *m_graphics_line_item_left = nullptr;         //左路侧竖红线对象
    QGraphicsLineItem *m_graphics_line_item_right = nullptr;        //右侧竖红线对象
    QLabel *m_size_label = nullptr;                                 //裁剪后的图像矩形尺寸显示
    QRect m_crop_rect;                                              //裁剪后的图像矩形尺寸
    bool m_dragging_left = false;                                   //左侧线是否选中
    bool m_dragging_right = false;                                  //右侧线是否选中
    int m_pure_image_width = 0;                                     //原始图像的宽度
    bool m_is_first_load_image = true;
};

#endif // MYQGRAPHICSVIEW_H