核心: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);
}