QT实现SVG无背景完整显示,缩放拖动,添加图片到SVG图中

核心:QGraphicsView在Qt中作为可滚动视口,展示QGraphicsScene的内容

SVG无背景

html代码中确保有fill="transparent",要不然直接加载会有黑色背景。

QGraphicsView类

参考博客:Qt图形视图框架:QGraphicsView 详解-CSDN博客

QGraphicsScene类

参考博客:Qt图形视图框架:QGraphicsScene详解-CSDN博客

代码

QGraphicsView初始化

// 自定义视图类实现
SvgView::SvgView(QGraphicsScene *scene, QWidget *parent)
    : QGraphicsView(scene, parent)
{
        setRenderHint(QPainter::Antialiasing);//图片抗锯齿
        setRenderHint(QPainter::TextAntialiasing);//文本抗锯齿
        setRenderHint(QPainter::SmoothPixmapTransform);使图像变换过程更加平滑,减少锯齿状边缘的出现
        setDragMode(QGraphicsView::ScrollHandDrag); // 启用手形拖动

        // 禁用滚动条
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

        // 设置视图锚点为中心,确保缩放时内容居中
        setResizeAnchor(QGraphicsView::AnchorViewCenter);
}

void SvgView::wheelEvent(QWheelEvent *event)
{
    if (event->modifiers() & Qt::ControlModifier) {
        // Ctrl+滚轮:执行缩放
        double factor = 1.2;
        if (event->angleDelta().y() < 0) {
            factor = 1 / factor;  // 向下滚动缩小
        }
        emit zoomed(factor);
        event->accept();
    } else {
        // 普通滚轮:保持默认滚动行为
        QGraphicsView::wheelEvent(event);
    }
}

主窗口类

// 主窗口类实现
MySvg_WidgetTest::MySvg_WidgetTest(QWidget *parent)
    : QSvgWidget(parent)
    , ui(new Ui::MySvg_WidgetTest)
    , scaleFactor(1.0)
{
    ui->setupUi(this);
    resize(614, 419);

        scene = new QGraphicsScene(this);
        view = new SvgView(scene, this);
        view->resize(614,419);
        //ctrl滚轮缩放
        connect(view, &SvgView::zoomed, this, &MySvg_WidgetTest::handleZoom);

        // 先创建新的图片项加载在场景中
        carPixmap = QPixmap(":/car.png");
        if (carPixmap.isNull()) qDebug() << "Error loading car image!";
        carItem = new QGraphicsPixmapItem(carPixmap); 
        //车辆大小显示
        carItem->setScale(0.01);
        carItem->setZValue(1);  // 确保在顶层
        carItem->setVisible(false);
        scene->addItem(carItem);//添加到视图中

        // 后加载地图
        //loadSvg("jindaditu.svg");
}

MySvg_WidgetTest::~MySvg_WidgetTest()
{
    delete ui;
}
//加载svg图片
void MySvg_WidgetTest::loadSvg(const QString &fileName) {
    // 删除所有现有地图项(仅删除QGraphicsSvgItem类型)
    QList<QGraphicsItem*> items = scene->items();
    for (QGraphicsItem* item : items) {
        if (item->type() == QGraphicsSvgItem::Type) {
            scene->removeItem(item);
            delete item;
        }
    }

    // 加载新地图
    QGraphicsSvgItem *svgItem = new QGraphicsSvgItem(fileName);
    svgItem->setFlags(QGraphicsSvgItem::ItemClipsToShape);//项目剪辑成它自己的形状。
    svgItem->setCacheMode(QGraphicsSvgItem::NoCache);//不渲染直接显示
    scene->addItem(svgItem);//SVG添加到视图

    // 设置场景边界
    QRectF bounds = svgItem->boundingRect();
    scene->setSceneRect(bounds);

    currentFile = fileName;
    _initSize = view->size();
    fitToView();
}

void MySvg_WidgetTest::carposion(double x,double y,double angle ){
    // 设置车辆位置和旋转角度
    carItem->setPos(QPointF(x,y));
    carItem->setRotation(angle);
    carItem->setVisible(true);
}


//填充widget
void MySvg_WidgetTest::fitToView() {
    if (scene->items().isEmpty()) return;

    QRectF svgRect = scene->itemsBoundingRect();//创建Rect来框边界
    QSize targetSize(614, 419);
    QMargins margins(10, 10, 10, 10);
    QSize viewportSize = targetSize - QSize(margins.left()+margins.right(),
                                          margins.top()+margins.bottom());  //视口尺寸

    // 计算缩放比例
    double scale;
    if (svgRect.width()/svgRect.height() > viewportSize.width()/viewportSize.height()) {
        scale = viewportSize.width() / svgRect.width();
    } else {
        scale = viewportSize.height() / svgRect.height();
    }

    // 应用缩放但不调整中心
    view->resetTransform();
    view->scale(scale, scale);
    scaleFactor = scale;
}

//缩放槽函数
void MySvg_WidgetTest::handleZoom(double factor) {
    if (!carItem || !carItem->isVisible()) return;

    // 保存车辆场景坐标
    QPointF carPos = carItem->pos();

    // 执行缩放
    view->scale(factor, factor);
    scaleFactor *= factor;

    // 缩放后重新对准车辆位置
    view->centerOn(carPos);
}

void MySvg_WidgetTest::zoomIn()
{
    scaleFactor *= 1.2;
    view->scale(1.2, 1.2);
}

void MySvg_WidgetTest::zoomOut()
{
    scaleFactor /= 1.2;
    view->scale(1/1.2, 1/1.2);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值