#include "mygraphicsview.h" #include #include #include #include #include #include MyGraphicsView::ClipInfo MyGraphicsView::clipboard_ = {}; MyGraphicsView::MyGraphicsView(QWidget *parent) : QGraphicsView(parent) { setAcceptDrops(true); setRenderHint(QPainter::Antialiasing); setFocusPolicy(Qt::StrongFocus); setDragMode(QGraphicsView::RubberBandDrag); } void MyGraphicsView::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("application/x-component")) event->acceptProposedAction(); else event->ignore(); } void MyGraphicsView::dragMoveEvent(QDragMoveEvent *event) { if (event->mimeData()->hasFormat("application/x-component")) event->acceptProposedAction(); else event->ignore(); } void MyGraphicsView::dropEvent(QDropEvent *event) { if (!event->mimeData()->hasFormat("application/x-component")) { event->ignore(); return; } QString type = QString::fromUtf8(event->mimeData()->data("application/x-component")); QPointF scenePos = mapToScene(event->pos()); Item *item = creatItem(type); item->setPos(scenePos); connect(item, &Item::requestCopy, this, &MyGraphicsView::onItemRequestCopy); connect(item, &Item::requestDelete, this, &MyGraphicsView::onItemRequestDelete); connect(item, &Item::requestBindRegister, this, &MyGraphicsView::onItemRequestBindRegister); scene()->addItem(item); event->acceptProposedAction(); } void MyGraphicsView::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Delete && scene()) { QList selectedItems = scene()->selectedItems(); for (QGraphicsItem* item : selectedItems) { if (auto conn = dynamic_cast(item)) { // 先通知两端节点断开 conn->from_->removeConnection(conn); conn->to_->removeConnection(conn); scene()->removeItem(conn); delete conn; } else if (auto node = dynamic_cast(item)) { // 删除节点的所有连线 QList conns = node->connections(); for (Connection* conn : conns) { conn->from_->removeConnection(conn); conn->to_->removeConnection(conn); scene()->removeItem(conn); delete conn; } scene()->removeItem(node); delete node; } } }else if (event->matches(QKeySequence::Copy)) { // Ctrl+C QList selectedItems = scene()->selectedItems(); for (QGraphicsItem* item : selectedItems) { if (auto node = dynamic_cast(item)) { clipboard_.input = node->itemType(); break; } } } else if (event->matches(QKeySequence::Paste)) { // Ctrl+V if (!clipboard_.input.isEmpty()) { QPointF center = mapToScene(viewport()->rect().center()); Item* newItem = creatItem(clipboard_.input); newItem->setPos(center); connect(newItem, &Item::requestCopy, this, &MyGraphicsView::onItemRequestCopy); connect(newItem, &Item::requestDelete, this, &MyGraphicsView::onItemRequestDelete); connect(newItem, &Item::requestBindRegister, this, &MyGraphicsView::onItemRequestBindRegister); scene()->addItem(newItem); } } else { QGraphicsView::keyPressEvent(event); } } void MyGraphicsView::contextMenuEvent(QContextMenuEvent *event) { QPointF scenePos = mapToScene(event->pos()); QList itemsAt = scene()->items(scenePos); if (itemsAt.isEmpty() && !clipboard_.input.isEmpty()) { QMenu menu; QAction* pasteAct = menu.addAction("粘贴"); QAction* sel = menu.exec(event->globalPos()); if (sel == pasteAct) { Item* newItem = creatItem(clipboard_.input); newItem->setPos(scenePos); connect(newItem, &Item::requestCopy, this, &MyGraphicsView::onItemRequestCopy); connect(newItem, &Item::requestDelete, this, &MyGraphicsView::onItemRequestDelete); connect(newItem, &Item::requestBindRegister, this, &MyGraphicsView::onItemRequestBindRegister); scene()->addItem(newItem); } } else { QGraphicsView::contextMenuEvent(event); // 让Item自己弹出菜单 } } // ----------- 连线交互 ------------ Item* MyGraphicsView::anchorItemAt(const QPoint& viewPos, Item::AnchorType& anchorType) { QPointF scenePos = mapToScene(viewPos); for (QGraphicsItem* item : scene()->items(scenePos)) { if (Item* node = dynamic_cast(item)) { QRectF r = node->boundingRect(); QPointF local = node->mapFromScene(scenePos); if (QLineF(local, QPointF(r.left(), r.center().y())).length() < 10) { anchorType = Item::Left; return node; } if (QLineF(local, QPointF(r.right(), r.center().y())).length() < 10) { anchorType = Item::Right; return node; } } } return nullptr; } void MyGraphicsView::onItemRequestCopy(Item *item) { clipboard_.input = item->itemType(); } void MyGraphicsView::onItemRequestDelete(Item *item) { QList conns = item->connections(); for (Connection* conn : conns) { conn->from_->removeConnection(conn); conn->to_->removeConnection(conn); scene()->removeItem(conn); delete conn; } scene()->removeItem(item); delete item; } void MyGraphicsView::onItemRequestBindRegister(Item *item) { bool ok = false; QString reg = QInputDialog::getText(this, "寄存器", "编号:", QLineEdit::Normal, item->registerId(), &ok); if (ok && !reg.isEmpty()) { item->setRegisterId(reg); // 可选:在图元上显示寄存器编号 item->update(); } } void MyGraphicsView::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { Item::AnchorType anchor; Item* node = anchorItemAt(event->pos(), anchor); if (node) { drawingConnection_ = true; startItem_ = node; startAnchor_ = anchor; tempLine_ = scene()->addLine(QLineF(node->anchorPos(anchor), mapToScene(event->pos())), QPen(Qt::darkGray, 2, Qt::DashLine)); return; } } QGraphicsView::mousePressEvent(event); } void MyGraphicsView::mouseMoveEvent(QMouseEvent *event) { if (drawingConnection_ && tempLine_) { QLineF l = tempLine_->line(); l.setP2(mapToScene(event->pos())); tempLine_->setLine(l); return; } QGraphicsView::mouseMoveEvent(event); } void MyGraphicsView::mouseReleaseEvent(QMouseEvent *event) { if (drawingConnection_ && tempLine_) { // 检查鼠标释放点是否在某个Item boundingRect内 QPointF scenePos = mapToScene(event->pos()); for (QGraphicsItem* item : scene()->items(scenePos)) { if (Item* node = dynamic_cast(item)) { QRectF r = node->boundingRect(); QPointF local = node->mapFromScene(scenePos); // 计算落点距离左右端点 double distLeft = QLineF(local, QPointF(r.left(), r.center().y())).length(); double distRight = QLineF(local, QPointF(r.right(), r.center().y())).length(); Item::AnchorType anchor = (distLeft < distRight) ? Item::Left : Item::Right; // 生成连线 Connection* conn = new Connection(startItem_, startAnchor_, node, anchor); scene()->addItem(conn); break; } } // 清除临时线 scene()->removeItem(tempLine_); delete tempLine_; tempLine_ = nullptr; drawingConnection_ = false; startItem_ = nullptr; return; } QGraphicsView::mouseReleaseEvent(event); }