#include "mainwindow.h" #include "ui_mainwindow.h" #include "item.h" #include #include #include #include #include #include #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); /* 1. 场景 */ m_scene = new QGraphicsScene(this); ui->graphicsView->setScene(m_scene); ui->graphicsView->setSceneRect(0, 0, 800, 600); ui->graphicsView->setDragMode(QGraphicsView::RubberBandDrag); /* 2. 列表 */ ui->listWidget->setViewMode(QListView::IconMode); ui->listWidget->setIconSize(QSize(60, 30)); ui->listWidget->setDragEnabled(false); ui->listWidget->viewport()->installEventFilter(this); /* 3. 填充列表 */ createComponents(); } MainWindow::~MainWindow() { delete ui; } /* ---------- 拖拽核心 ---------- */ bool MainWindow::eventFilter(QObject *obj, QEvent *event) { if (obj == ui->listWidget->viewport()) { static QListWidgetItem *dragItem = nullptr; static QPoint startPos; if (event->type() == QEvent::MouseButtonPress) { auto *me = static_cast(event); if (me->button() == Qt::LeftButton) { dragItem = ui->listWidget->itemAt(me->pos()); startPos = me->pos(); } } else if (event->type() == QEvent::MouseMove && dragItem) { auto *me = static_cast(event); if ((me->pos() - startPos).manhattanLength() >= QApplication::startDragDistance()) { QString type = dragItem->data(Qt::UserRole).toString(); QMimeData *mime = new QMimeData; mime->setData("application/x-component", type.toUtf8()); QDrag *drag = new QDrag(this); drag->setMimeData(mime); drag->setPixmap(dragItem->icon().pixmap(ui->listWidget->iconSize())); drag->setHotSpot(drag->pixmap().rect().center()); drag->exec(Qt::CopyAction); dragItem = nullptr; } } else if (event->type() == QEvent::MouseButtonRelease) { dragItem = nullptr; } } return QMainWindow::eventFilter(obj, event); } /* ---------- 填充列表 ---------- */ void MainWindow::createComponents() { struct Comp { QString name; QColor color; }; const QVector comps = { {"常开", Qt::blue}, {"常闭", Qt::red}, {"比较", Qt::green}, {"线圈", Qt::darkYellow} }; for (const Comp &c : comps) { QListWidgetItem *it = new QListWidgetItem(c.name, ui->listWidget); QPixmap pix(60, 30); pix.fill(Qt::white); QPainter p(&pix); p.setRenderHint(QPainter::Antialiasing); p.setBrush(c.color.lighter(150)); p.setPen(QPen(c.color, 2)); p.drawRoundedRect(QRect(5, 5, 50, 20), 3, 3); p.setPen(Qt::black); p.drawText(QRect(5, 5, 50, 20), Qt::AlignCenter, c.name); it->setIcon(QIcon(pix)); it->setData(Qt::UserRole, c.name); } } void MainWindow::on_listWidget_currentTextChanged(const QString &text) { selectedComponentType = text; } void MainWindow::on_pushButton_clicked() { // 1. 找场景中被选中的连线 QList selectedItems = ui->graphicsView->scene()->selectedItems(); Connection* selectedConn = nullptr; for (QGraphicsItem* item : selectedItems) { selectedConn = dynamic_cast(item); if (selectedConn) break; } if (!selectedConn) { QMessageBox::warning(this, "提示", "请先选中一条连线"); return; } if (selectedComponentType.isEmpty()) { QMessageBox::warning(this, "提示", "请先在列表中选择要插入的组件"); return; } // 2. 计算插入点(中点) QLineF lf = selectedConn->line(); QPointF insertPos = (lf.p1() + lf.p2()) / 2; // 3. 删除原连线 Item* from = selectedConn->from_; Item* to = selectedConn->to_; Item::AnchorType fromType = selectedConn->fromType_; Item::AnchorType toType = selectedConn->toType_; from->removeConnection(selectedConn); to->removeConnection(selectedConn); ui->graphicsView->scene()->removeItem(selectedConn); delete selectedConn; // 4. 插入新元件 Item* newItem = new Item(selectedComponentType); newItem->setPos(insertPos); connect(newItem, &Item::requestCopy, ui->graphicsView, &MyGraphicsView::onItemRequestCopy); connect(newItem, &Item::requestDelete, ui->graphicsView, &MyGraphicsView::onItemRequestDelete); ui->graphicsView->scene()->addItem(newItem); // 5. 新建两条连线 Connection* c1 = new Connection(from, fromType, newItem, Item::Left); ui->graphicsView->scene()->addItem(c1); Connection* c2 = new Connection(newItem, Item::Right, to, toType); ui->graphicsView->scene()->addItem(c2); }