|
@@ -0,0 +1,213 @@
|
|
|
+#include "ImageView.h"
|
|
|
+#include <QPainter>
|
|
|
+#include <QDebug>
|
|
|
+#include <QGraphicsPixmapItem>
|
|
|
+#include <QScrollBar>
|
|
|
+#include <QMenu>
|
|
|
+#include <QFileDialog>
|
|
|
+#include <QDateTime>
|
|
|
+#include <QMessageBox>
|
|
|
+
|
|
|
+#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();
|
|
|
+}
|