Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

159 rindas
5.1 KiB

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include "item.h"
  4. #include <QListWidgetItem>
  5. #include <QMimeData>
  6. #include <QDrag>
  7. #include <QPainter>
  8. #include <QMouseEvent>
  9. #include <QDropEvent>
  10. #include <QGraphicsView>
  11. #include <QMessageBox>
  12. MainWindow::MainWindow(QWidget *parent)
  13. : QMainWindow(parent)
  14. , ui(new Ui::MainWindow)
  15. {
  16. ui->setupUi(this);
  17. /* 1. 场景 */
  18. m_scene = new QGraphicsScene(this);
  19. ui->graphicsView->setScene(m_scene);
  20. ui->graphicsView->setSceneRect(0, 0, 800, 600);
  21. ui->graphicsView->setDragMode(QGraphicsView::RubberBandDrag);
  22. /* 2. 列表 */
  23. ui->listWidget->setViewMode(QListView::IconMode);
  24. ui->listWidget->setIconSize(QSize(60, 30));
  25. ui->listWidget->setDragEnabled(false);
  26. ui->listWidget->viewport()->installEventFilter(this);
  27. /* 3. 填充列表 */
  28. createComponents();
  29. }
  30. MainWindow::~MainWindow()
  31. {
  32. delete ui;
  33. }
  34. /* ---------- 拖拽核心 ---------- */
  35. bool MainWindow::eventFilter(QObject *obj, QEvent *event)
  36. {
  37. if (obj == ui->listWidget->viewport()) {
  38. static QListWidgetItem *dragItem = nullptr;
  39. static QPoint startPos;
  40. if (event->type() == QEvent::MouseButtonPress) {
  41. auto *me = static_cast<QMouseEvent*>(event);
  42. if (me->button() == Qt::LeftButton) {
  43. dragItem = ui->listWidget->itemAt(me->pos());
  44. startPos = me->pos();
  45. }
  46. } else if (event->type() == QEvent::MouseMove && dragItem) {
  47. auto *me = static_cast<QMouseEvent*>(event);
  48. if ((me->pos() - startPos).manhattanLength()
  49. >= QApplication::startDragDistance()) {
  50. QString type = dragItem->data(Qt::UserRole).toString();
  51. QMimeData *mime = new QMimeData;
  52. mime->setData("application/x-component", type.toUtf8());
  53. QDrag *drag = new QDrag(this);
  54. drag->setMimeData(mime);
  55. drag->setPixmap(dragItem->icon().pixmap(ui->listWidget->iconSize()));
  56. drag->setHotSpot(drag->pixmap().rect().center());
  57. drag->exec(Qt::CopyAction);
  58. dragItem = nullptr;
  59. }
  60. } else if (event->type() == QEvent::MouseButtonRelease) {
  61. dragItem = nullptr;
  62. }
  63. }
  64. return QMainWindow::eventFilter(obj, event);
  65. }
  66. /* ---------- 填充列表 ---------- */
  67. void MainWindow::createComponents()
  68. {
  69. struct Comp { QString name; QColor color; };
  70. const QVector<Comp> comps = {
  71. {"常开", Qt::blue},
  72. {"常闭", Qt::red},
  73. {"比较", Qt::green},
  74. {"线圈", Qt::darkYellow}
  75. };
  76. for (const Comp &c : comps) {
  77. QListWidgetItem *it = new QListWidgetItem(c.name, ui->listWidget);
  78. QPixmap pix(60, 30);
  79. pix.fill(Qt::white);
  80. QPainter p(&pix);
  81. p.setRenderHint(QPainter::Antialiasing);
  82. p.setBrush(c.color.lighter(150));
  83. p.setPen(QPen(c.color, 2));
  84. p.drawRoundedRect(QRect(5, 5, 50, 20), 3, 3);
  85. p.setPen(Qt::black);
  86. p.drawText(QRect(5, 5, 50, 20), Qt::AlignCenter, c.name);
  87. it->setIcon(QIcon(pix));
  88. it->setData(Qt::UserRole, c.name);
  89. }
  90. }
  91. void MainWindow::on_listWidget_currentTextChanged(const QString &text)
  92. {
  93. selectedComponentType = text;
  94. }
  95. void MainWindow::on_pushButton_clicked()
  96. {
  97. // 1. 找场景中被选中的连线
  98. QList<QGraphicsItem*> selectedItems = ui->graphicsView->scene()->selectedItems();
  99. Connection* selectedConn = nullptr;
  100. for (QGraphicsItem* item : selectedItems) {
  101. selectedConn = dynamic_cast<Connection*>(item);
  102. if (selectedConn) break;
  103. }
  104. if (!selectedConn) {
  105. QMessageBox::warning(this, "提示", "请先选中一条连线");
  106. return;
  107. }
  108. if (selectedComponentType.isEmpty()) {
  109. QMessageBox::warning(this, "提示", "请先在列表中选择要插入的组件");
  110. return;
  111. }
  112. // 2. 计算插入点(中点)
  113. QLineF lf = selectedConn->line();
  114. QPointF insertPos = (lf.p1() + lf.p2()) / 2;
  115. // 3. 删除原连线
  116. Item* from = selectedConn->from_;
  117. Item* to = selectedConn->to_;
  118. Item::AnchorType fromType = selectedConn->fromType_;
  119. Item::AnchorType toType = selectedConn->toType_;
  120. from->removeConnection(selectedConn);
  121. to->removeConnection(selectedConn);
  122. ui->graphicsView->scene()->removeItem(selectedConn);
  123. delete selectedConn;
  124. // 4. 插入新元件
  125. Item* newItem = new Item(selectedComponentType);
  126. newItem->setPos(insertPos);
  127. connect(newItem, &Item::requestCopy, ui->graphicsView, &MyGraphicsView::onItemRequestCopy);
  128. connect(newItem, &Item::requestDelete, ui->graphicsView, &MyGraphicsView::onItemRequestDelete);
  129. ui->graphicsView->scene()->addItem(newItem);
  130. // 5. 新建两条连线
  131. Connection* c1 = new Connection(from, fromType, newItem, Item::Left);
  132. ui->graphicsView->scene()->addItem(c1);
  133. Connection* c2 = new Connection(newItem, Item::Right, to, toType);
  134. ui->graphicsView->scene()->addItem(c2);
  135. }