#include "WaffleGraphicsView.h" #include #include WaffleGraphicsView::WaffleGraphicsView(QGraphicsScene* scene, QWidget* parent) : QGraphicsView(scene, parent), selecting(false), selectionRect(nullptr), scaleFactor(1.0), isDragging(false), thumbnailLabel(nullptr), thumbnailVisible(false) { setRenderHint(QPainter::Antialiasing); // setDragMode(QGraphicsView::ScrollHandDrag); // 支持拖动视图 setTransformationAnchor(QGraphicsView::AnchorUnderMouse); // 缩放时以鼠标为中心 // 初始化缩略图标签 thumbnailLabel = new QLabel(this); thumbnailLabel->setFixedSize(150, 150); thumbnailLabel->move(0, 0); // 默认左上角位置 thumbnailLabel->setStyleSheet("background-color: white; border: 1px solid gray;"); thumbnailLabel->installEventFilter(this); thumbnailLabel->hide(); topLeftIndex = qMakePair(-1, -1); bottomRightIndex = qMakePair(-1, -1); } // 事件过滤器用于处理缩略图拖动 bool WaffleGraphicsView::eventFilter(QObject *obj, QEvent *event) { static QPoint dragStartPosition; if (obj == thumbnailLabel) { if (event->type() == QEvent::MouseButtonPress) { QMouseEvent *me = static_cast(event); dragStartPosition = me->pos(); return true; } else if (event->type() == QEvent::MouseMove) { QMouseEvent *me = static_cast(event); // 计算新位置 QPoint newPos = thumbnailLabel->pos() + (me->pos() - dragStartPosition); // 限制在视图范围内 int maxX = this->width() - thumbnailLabel->width(); int maxY = this->height() - thumbnailLabel->height(); // 使用qBound限制坐标范围(0 <= x <= maxX,0 <= y <= maxY) newPos.setX(qBound(0, newPos.x(), maxX)); newPos.setY(qBound(0, newPos.y(), maxY)); thumbnailLabel->move(newPos); return true; } } return QGraphicsView::eventFilter(obj, event); } void WaffleGraphicsView::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { // 清空选中的 DieItem for (auto& item : selectedItemsMap) { DieItem* die = dynamic_cast(item); if (die) { die->setSelected(false); // 取消选中状态 } } selectedItemsMap.clear(); if (topLeftItem && topLeftItem->scene()) { topLeftItem->setRightSelected(false); } topLeftItem.clear(); if (bottomRightItem && bottomRightItem->scene()) { bottomRightItem->setRightSelected(false); } bottomRightItem.clear(); topLeftIndex = qMakePair(-1, -1); bottomRightIndex = qMakePair(-1, -1); // 获取点击位置的 DieItem if (selectedItem && selectedItem->scene()) { selectedItem->setLeftSelected(false); } selectedItem.clear(); QGraphicsItem* item = itemAt(event->pos()); if (item) { selectedItem = dynamic_cast(item); selectedItem->setLeftSelected(true); } setCursor(Qt::OpenHandCursor); // 按下时设置为小手 selecting = true; lastPos = event->pos(); // 记录鼠标位置 } else if (event->button() == Qt::RightButton) { // 开始框选 selecting = true; selectionStart = mapToScene(event->pos()); isDragging = false; if (!selectionRect) { selectionRect = new QGraphicsRectItem(); selectionRect->setPen(QPen(Qt::NoPen)); selectionRect->setBrush(QBrush(QColor(0, 0, 255, 50))); // 半透明蓝色 scene()->addItem(selectionRect); } selectionRect->setRect(QRectF(selectionStart, QSizeF())); } QGraphicsView::mousePressEvent(event); } void WaffleGraphicsView::mouseMoveEvent(QMouseEvent* event) { if (selecting && selectionRect) { QPointF currentPos = mapToScene(event->pos()); selectionRect->setRect(QRectF(selectionStart, currentPos).normalized()); isDragging = true; } else if (selecting) { // 计算鼠标当前位置与上次位置的差值 QPointF delta = event->pos() - lastPos; // 平移视图 horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x()); verticalScrollBar()->setValue(verticalScrollBar()->value() - delta.y()); lastPos = event->pos(); // 更新鼠标位置 } QGraphicsView::mouseMoveEvent(event); } void WaffleGraphicsView::mouseReleaseEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { setCursor(Qt::ArrowCursor); // 松开时恢复为箭头 selecting = false; } else if (event->button() == Qt::RightButton && selecting) { selecting = false; if (selectionRect && isDragging) { if (selectedItem && selectedItem->scene()) { selectedItem->setLeftSelected(false); } selectedItem.clear(); if (topLeftItem && topLeftItem->scene()) { topLeftItem->setRightSelected(false); } topLeftItem.clear(); if (bottomRightItem && bottomRightItem->scene()) { bottomRightItem->setRightSelected(false); } bottomRightItem.clear(); topLeftIndex = qMakePair(-1, -1); bottomRightIndex = qMakePair(-1, -1); QRectF selectedArea = selectionRect->rect(); scene()->removeItem(selectionRect); delete selectionRect; selectionRect = nullptr; QList items = scene()->items(selectedArea, Qt::IntersectsItemShape); for (QGraphicsItem* item : items) { DieItem* die = dynamic_cast(item); if (die) { // 将 DieItem 添加到 map 中 selectedItemsMap.insert(qMakePair(die->getRow(), die->getCol()), die); die->setSelected(true); // 设置选中状态 } } } if (selectionRect) { scene()->removeItem(selectionRect); delete selectionRect; selectionRect = nullptr; } // 如果没有进行拖动,则弹出右键菜单 if (!isDragging) { QGraphicsItem* item = itemAt(event->pos()); DieItem* die = dynamic_cast(item); QMenu menu; QAction* showThumb = menu.addAction(thumbnailVisible ? "隐藏缩略图" : "显示缩略图"); connect(showThumb, &QAction::triggered, [this]{ thumbnailVisible ? hideThumbnail() : showThumbnail(); }); menu.addAction("发送位置", [this] { if (selectedItem) { qDebug() << "Row:" << selectedItem->getRow() << "Col:" << selectedItem->getCol(); selectedItem->setLeftSelected(false); selectedItem = nullptr; } }); if (die) { menu.addAction("移动到该位置", [this, die] { for (auto& item : selectedItemsMap) { DieItem* die = dynamic_cast(item); if (die) { die->setSelected(false); } } selectedItemsMap.clear(); if (topLeftItem && topLeftItem->scene()) { topLeftItem->setRightSelected(false); } topLeftItem.clear(); if (bottomRightItem && bottomRightItem->scene()) { bottomRightItem->setRightSelected(false); } bottomRightItem.clear(); topLeftIndex = qMakePair(-1, -1); bottomRightIndex = qMakePair(-1, -1); if (selectedItem && selectedItem->scene()) { selectedItem->setLeftSelected(false); } selectedItem.clear(); selectedItem = die; selectedItem->setLeftSelected(true); }); // 设置区域边界点菜单 menu.addAction("设为左上点", [this, die] { if (topLeftItem && topLeftItem->scene()) { topLeftItem->setRightSelected(false); } topLeftItem.clear(); topLeftItem = die; topLeftItem->setRightSelected(true); topLeftIndex = qMakePair(die->getRow(), die->getCol()); if (bottomRightIndex.first >= 0) checkAndCreateRegion(); }); menu.addAction("设为右下点", [this, die] { if (bottomRightItem && bottomRightItem->scene()) { bottomRightItem->setRightSelected(false); } bottomRightItem.clear(); bottomRightItem = die; bottomRightItem->setRightSelected(true); bottomRightIndex = qMakePair(die->getRow(), die->getCol()); if (topLeftIndex.first >= 0) checkAndCreateRegion(); }); } menu.addAction("清除选中区域", [this] { clearRegion(); }); menu.addAction("设置区域", [this] { setRegion(); }); menu.exec(event->globalPos()); } } QGraphicsView::mouseReleaseEvent(event); } void WaffleGraphicsView::wheelEvent(QWheelEvent* event) { if (event->orientation() == Qt::Vertical) { event->ignore(); // 忽略竖直滚轮事件(即禁用滚动条滑动) return; } event->accept(); } // 缩略图功能实现 void WaffleGraphicsView::showThumbnail() { // 本地图片路径(根据实际路径修改) QString imagePath = ":/images/test_image/image_1.png"; // 替换为本地图片路径 // 加载本地图片 QPixmap thumb(imagePath); if (!thumb.isNull()) { // 如果图片加载成功,设置为缩略图 thumbnailLabel->setPixmap(thumb.scaled(150, 150, Qt::KeepAspectRatio)); thumbnailLabel->show(); thumbnailVisible = true; } else { // 如果加载图片失败,显示"图片加载失败" thumbnailLabel->setText("图片加载失败"); thumbnailLabel->setAlignment(Qt::AlignCenter); // 居中显示文本 thumbnailLabel->show(); thumbnailVisible = true; } } void WaffleGraphicsView::hideThumbnail() { thumbnailLabel->hide(); thumbnailVisible = false; thumbnailLabel->move(0, 0); } void WaffleGraphicsView::checkAndCreateRegion() { // 仅当两个点都有效时处理 if (topLeftIndex.first < 0 || bottomRightIndex.first < 0) return; // 确定行列范围 int startRow = qMin(topLeftIndex.first, bottomRightIndex.first); int endRow = qMax(topLeftIndex.first, bottomRightIndex.first); int startCol = qMin(topLeftIndex.second, bottomRightIndex.second); int endCol = qMax(topLeftIndex.second, bottomRightIndex.second); // 遍历场景中的所有项 foreach (QGraphicsItem* item, scene()->items()) { if (DieItem* die = dynamic_cast(item)) { int row = die->getRow(); int col = die->getCol(); // 判断是否在区域内 if (row >= startRow && row <= endRow && col >= startCol && col <= endCol) { // 更新选中状态 die->setSelected(true); selectedItemsMap.insert(qMakePair(row, col), die); } } } // 重置索引点 topLeftIndex = qMakePair(-1, -1); bottomRightIndex = qMakePair(-1, -1); } void WaffleGraphicsView::clearRegion() { // 清空选中的 DieItem for (auto& item : selectedItemsMap) { DieItem* die = dynamic_cast(item); if (die) { die->setSelected(false); // 取消选中状态 } } selectedItemsMap.clear(); if (selectedItem && selectedItem->scene()) { selectedItem->setLeftSelected(false); } selectedItem.clear(); if (topLeftItem && topLeftItem->scene()) { topLeftItem->setRightSelected(false); } topLeftItem.clear(); if (bottomRightItem && bottomRightItem->scene()) { bottomRightItem->setRightSelected(false); } bottomRightItem.clear(); topLeftIndex = qMakePair(-1, -1); bottomRightIndex = qMakePair(-1, -1); // 清除缩略图 hideThumbnail(); } void WaffleGraphicsView::setRegion() { for (auto it = selectedItemsMap.begin(); it != selectedItemsMap.end(); ++it) { QPair key = it.key(); // 获取当前元素的 key qDebug() << "Row:" << key.first << ", Col:" << key.second; } // 清空选中的 DieItem for (auto& item : selectedItemsMap) { DieItem* die = dynamic_cast(item); if (die) { die->setSelected(false); // 取消选中状态 } } selectedItemsMap.clear(); if (selectedItem && selectedItem->scene()) { selectedItem->setLeftSelected(false); } selectedItem.clear(); if (topLeftItem && topLeftItem->scene()) { topLeftItem->setRightSelected(false); } topLeftItem.clear(); if (bottomRightItem && bottomRightItem->scene()) { bottomRightItem->setRightSelected(false); } bottomRightItem.clear(); topLeftIndex = qMakePair(-1, -1); bottomRightIndex = qMakePair(-1, -1); }