#include "ImageView.h" #include #include #include #include #include #include #include #include #define VIEW_CENTER viewport()->rect().center() #define VIEW_WIDTH viewport()->rect().width() #define VIEW_HEIGHT viewport()->rect().height() ImageView::ImageView(QWidget* parent) : QGraphicsView(parent), m_imageOffset(0, 0), m_bMouseTranslate(false), m_isDrawing(false), m_curDrawing(false), m_currentPathItem(nullptr) { m_pRuleLine = nullptr; setScene(new QGraphicsScene(this)); setRenderHint(QPainter::SmoothPixmapTransform); setTransformationAnchor(QGraphicsView::AnchorUnderMouse); this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } ImageView::~ImageView() { } void ImageView::setPixmap(const QPixmap& newPixmap) { this->m_pixmap = newPixmap; scene()->clear(); m_pixmapItem = scene()->addPixmap(m_pixmap); m_pixmapItem->setZValue(1); QPointF pixmapCenter(m_pixmap.width() / 2.0, m_pixmap.height() / 2.0); m_pixmapItem->setPos(-pixmapCenter); QRectF sceneRect(-pixmapCenter.x(), -pixmapCenter.y(), m_pixmap.width(), m_pixmap.height()); scene()->setSceneRect(sceneRect); setSceneRect(scene()->itemsBoundingRect()); this->resize(m_pixmap.width(), m_pixmap.height()); m_imageOffset = QPoint(0, 0); // 重置图片偏移量为(0, 0) setCursor(Qt::ArrowCursor); update(); // 触发重绘 } void ImageView::setCurPixmap(const QPixmap& newPixmap) { this->m_pixmap = newPixmap; m_pixmapItem->setPixmap(m_pixmap); } void ImageView::startRuler() { if (nullptr == m_pRuleLine) { m_pRuleLine = new DraggableLine(QLineF(0, 0, 50, 50)); m_pRuleLine->setPen(QPen(Qt::red, 2)); m_pRuleLine->setZValue(2); scene()->addItem(m_pRuleLine); } } void ImageView::endRuler() { if (nullptr != m_pRuleLine) { scene()->removeItem(m_pRuleLine); delete m_pRuleLine; m_pRuleLine = nullptr; } } bool ImageView::rulerVisibale() { if (nullptr == m_pRuleLine) return false; else return true; } void ImageView::paintEvent(QPaintEvent* event) { QGraphicsView::paintEvent(event); } void ImageView::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { // 当光标底下没有 item 时,才能移动 QPointF point = mapToScene(event->pos()); if (scene()->itemAt(point, transform()) != m_pRuleLine) { setCursor(Qt::OpenHandCursor); m_bMouseTranslate = true; m_lastMousePos = event->pos(); } } else if (event->button() == Qt::RightButton) { m_rightClickPressPos = event->pos(); m_rightButtonPressed = true; } QGraphicsView::mousePressEvent(event); } void ImageView::mouseMoveEvent(QMouseEvent* event) { if (m_bMouseTranslate) { // 计算鼠标当前位置与上次位置的差值 QPointF delta = event->pos() - m_lastMousePos; // 平移视图 horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x()); verticalScrollBar()->setValue(verticalScrollBar()->value() - delta.y()); m_lastMousePos = event->pos(); // 更新鼠标位置 } else if ((event->buttons() & Qt::RightButton) && m_isDrawing && m_rightButtonPressed) { if (!m_curDrawing && (event->pos() - m_rightClickPressPos).manhattanLength() > 5) { m_curDrawing = true; // 根据初始位置开始绘制路径 QPointF scenePos = mapToScene(m_rightClickPressPos); m_currentPath = QPainterPath(scenePos); m_currentPathItem = new QGraphicsPathItem(); m_currentPathItem->setPen(QPen(Qt::red, 2)); m_currentPathItem->setPath(m_currentPath); m_currentPathItem->setZValue(2); scene()->addItem(m_currentPathItem); m_drawnPaths.append(m_currentPathItem); } // 如果已经处于绘制状态,则继续添加点 if (m_curDrawing && m_currentPathItem) { QPointF scenePos = mapToScene(event->pos()); m_currentPath.lineTo(scenePos); m_currentPathItem->setPath(m_currentPath); } event->accept(); return; } QGraphicsView::mouseMoveEvent(event); } void ImageView::mouseReleaseEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { setCursor(Qt::ArrowCursor); // 松开时恢复为箭头 m_bMouseTranslate = false; } else if (event->button() == Qt::RightButton && m_rightButtonPressed) { if (!m_curDrawing) { // 右键点击(无拖动),弹出菜单 QMenu menu(this); QAction* act1 = menu.addAction(tr("保存当前窗口图片")); QAction* act2 = menu.addAction(tr("清除")); connect(act1, &QAction::triggered, this, [this]() { saveImage(); }); connect(act2, &QAction::triggered, this, [this]() { clearDrawnLines(); }); menu.exec(event->globalPos()); } else { // 绘制结束 m_currentPathItem = nullptr; m_curDrawing = false; } // 恢复状态 m_rightButtonPressed = false; event->accept(); return; } QGraphicsView::mouseReleaseEvent(event); } void ImageView::wheelEvent(QWheelEvent* event) { if (event->orientation() == Qt::Vertical) { event->ignore(); // 忽略竖直滚轮事件(即禁用滚动条滑动) return; } event->accept(); } void ImageView::saveImage() { // 使用当前时间生成默认文件名 QString defaultFileName = QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm-ss") + ".png"; QString fileName = QFileDialog::getSaveFileName( this, tr("保存图片"), QDir::homePath() + "/" + defaultFileName, // 默认路径为用户目录,文件名为当前时间 tr("PNG 文件 (*.png);;JPEG 文件 (*.jpg);;所有文件 (*)") ); if (!fileName.isEmpty()) { QImage image(viewport()->size(), QImage::Format_ARGB32); image.fill(Qt::white); QPainter painter(&image); this->render(&painter); if (!image.save(fileName)) { QMessageBox::warning(this, tr("保存失败"), tr("无法保存图片到指定路径。")); } else { QMessageBox::information(this, tr("保存成功"), tr("图片已成功保存到:") + fileName); } painter.end(); } } void ImageView::clearDrawnLines() { qDeleteAll(m_drawnPaths); m_drawnPaths.clear(); }