From 0a6c228ec24c0be5bef3eccd40b017381d47c177 Mon Sep 17 00:00:00 2001 From: lipengpeng Date: Wed, 6 Aug 2025 08:38:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E7=9A=84=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E4=BB=A5=E8=BF=9B=E8=A1=8C=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E7=9A=84=E6=8B=96=E6=8B=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- editor.pro | 35 +++++ editor.pro.user | 320 +++++++++++++++++++++++++++++++++++++++++++++ item.cpp | 33 +++++ item.h | 22 ++++ main.cpp | 17 +++ mainwindow.cpp | 107 +++++++++++++++ mainwindow.h | 29 ++++ mainwindow.ui | 62 +++++++++ mygraphicsview.cpp | 63 +++++++++ mygraphicsview.h | 24 ++++ mylistwidget.cpp | 6 + mylistwidget.h | 31 +++++ 12 files changed, 749 insertions(+) create mode 100644 editor.pro create mode 100644 editor.pro.user create mode 100644 item.cpp create mode 100644 item.h create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui create mode 100644 mygraphicsview.cpp create mode 100644 mygraphicsview.h create mode 100644 mylistwidget.cpp create mode 100644 mylistwidget.h diff --git a/editor.pro b/editor.pro new file mode 100644 index 0000000..1357d6c --- /dev/null +++ b/editor.pro @@ -0,0 +1,35 @@ +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + item.cpp \ + main.cpp \ + mainwindow.cpp \ + mygraphicsview.cpp + +HEADERS += \ + item.h \ + mainwindow.h \ + mygraphicsview.h + +FORMS += \ + mainwindow.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/editor.pro.user b/editor.pro.user new file mode 100644 index 0000000..4eb1275 --- /dev/null +++ b/editor.pro.user @@ -0,0 +1,320 @@ + + + + + + EnvironmentId + {1084213a-f698-4faa-95c4-704b6a0911a5} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + -fno-delayed-template-parsing + + true + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.14.2 MinGW 64-bit + Desktop Qt 5.14.2 MinGW 64-bit + qt.qt5.5142.win64_mingw73_kit + 0 + 0 + 0 + + D:/National/Qt/Projects/build-editor-Desktop_Qt_5_14_2_MinGW_64_bit-Debug + + + true + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + D:/National/Qt/Projects/build-editor-Desktop_Qt_5_14_2_MinGW_64_bit-Release + + + true + QtProjectManager.QMakeBuildStep + false + + false + false + true + + + true + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + + + D:/National/Qt/Projects/build-editor-Desktop_Qt_5_14_2_MinGW_64_bit-Profile + + + true + QtProjectManager.QMakeBuildStep + true + + false + true + true + + + true + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + dwarf + + cpu-cycles + + + 250 + + -e + cpu-cycles + --call-graph + dwarf,4096 + -F + 250 + + -F + true + 4096 + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + kcachegrind + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + editor2 + Qt4ProjectManager.Qt4RunConfiguration:D:/work/editor/editor/editor.pro + D:/work/editor/editor/editor.pro + + false + + false + true + true + false + false + true + + D:/National/Qt/Projects/build-editor-Desktop_Qt_5_14_2_MinGW_64_bit-Debug + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/item.cpp b/item.cpp new file mode 100644 index 0000000..e807c91 --- /dev/null +++ b/item.cpp @@ -0,0 +1,33 @@ +#include "item.h" +#include +#include + +Item::Item(const QString &type, QGraphicsItem *parent) + : QGraphicsObject(parent), type_(type) +{ + if (type == "常开") color_ = Qt::blue; + else if (type == "常闭") color_ = Qt::red; + else if (type == "比较指令") color_ = Qt::green; + else color_ = Qt::darkYellow; + + setFlags(QGraphicsItem::ItemIsMovable | + QGraphicsItem::ItemIsSelectable | + QGraphicsItem::ItemSendsGeometryChanges); +} + +QRectF Item::boundingRect() const +{ + return QRectF(0, 0, 80, 40); +} + +void Item::paint(QPainter *painter, + const QStyleOptionGraphicsItem *, + QWidget *) +{ + painter->setBrush(color_.lighter(150)); + painter->setPen(QPen(color_, 2)); + painter->drawRoundedRect(boundingRect(), 5, 5); + + painter->setPen(Qt::black); + painter->drawText(boundingRect(), Qt::AlignCenter, type_); +} diff --git a/item.h b/item.h new file mode 100644 index 0000000..aac8d68 --- /dev/null +++ b/item.h @@ -0,0 +1,22 @@ +#ifndef ITEM_H +#define ITEM_H + +#include + +class Item : public QGraphicsObject +{ + Q_OBJECT +public: + explicit Item(const QString &type, QGraphicsItem *parent = nullptr); + + QRectF boundingRect() const override; + void paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget) override; + +private: + QString type_; + QColor color_; +}; + +#endif // ITEM_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..1136a77 --- /dev/null +++ b/main.cpp @@ -0,0 +1,17 @@ +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + // 设置应用程序信息 + QApplication::setApplicationName("PLC梯形图编辑器"); + QApplication::setApplicationVersion("1.0"); + + MainWindow w; + w.resize(1000, 600); + w.show(); + + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..03118be --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,107 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "item.h" + +#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->setRenderHint(QPainter::Antialiasing); + ui->graphicsView->setSceneRect(0, 0, 800, 600); + ui->graphicsView->setAcceptDrops(true); + ui->graphicsView->setFocus(); + + /* 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); + } +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..d0ae3a3 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,29 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +class QGraphicsScene; +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +private: + void createComponents(); + + Ui::MainWindow *ui; + QGraphicsScene *m_scene; +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..c59adba --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,62 @@ + + + MainWindow + + + + 0 + 0 + 1101 + 656 + + + + MainWindow + + + + + + 20 + 10 + 161 + 381 + + + + + + + 210 + 10 + 791 + 381 + + + + QGraphicsView::NoDrag + + + + + + + 0 + 0 + 1101 + 26 + + + + + + + + MyGraphicsView + QGraphicsView +
mygraphicsview.h
+
+
+ + +
diff --git a/mygraphicsview.cpp b/mygraphicsview.cpp new file mode 100644 index 0000000..b3584df --- /dev/null +++ b/mygraphicsview.cpp @@ -0,0 +1,63 @@ +#include "mygraphicsview.h" +#include +#include +#include +#include + +MyGraphicsView::MyGraphicsView(QWidget *parent) + : QGraphicsView(parent) +{ + setAcceptDrops(true); + viewport()->setAcceptDrops(true); + setRenderHint(QPainter::Antialiasing); + setFocusPolicy(Qt::StrongFocus); // 让view能接收键盘事件 +} + +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 = new Item(type); + item->setPos(scenePos); + + if (scene()) + 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) { + scene()->removeItem(item); + delete item; + } + } else { + QGraphicsView::keyPressEvent(event); + } +} diff --git a/mygraphicsview.h b/mygraphicsview.h new file mode 100644 index 0000000..e245c5a --- /dev/null +++ b/mygraphicsview.h @@ -0,0 +1,24 @@ +#ifndef MYGRAPHICSVIEW_H +#define MYGRAPHICSVIEW_H + +#include +#include +#include +#include +#include +#include "item.h" + +class MyGraphicsView : public QGraphicsView +{ + Q_OBJECT +public: + explicit MyGraphicsView(QWidget *parent = nullptr); + +protected: + void dragEnterEvent(QDragEnterEvent *event) override; + void dropEvent(QDropEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; +}; + +#endif // MYGRAPHICSVIEW_H diff --git a/mylistwidget.cpp b/mylistwidget.cpp new file mode 100644 index 0000000..31a4439 --- /dev/null +++ b/mylistwidget.cpp @@ -0,0 +1,6 @@ +#include "mylistwidget.h" + +MyListWidget::MyListWidget() +{ + +} diff --git a/mylistwidget.h b/mylistwidget.h new file mode 100644 index 0000000..5e5f1ea --- /dev/null +++ b/mylistwidget.h @@ -0,0 +1,31 @@ +#ifndef MYLISTWIDGET_H +#define MYLISTWIDGET_H +#include +#include +#include + +class MyListWidget : public QListWidget { +public: + using QListWidget::QListWidget; + +protected: + void startDrag(Qt::DropActions supportedActions) override + { + QListWidgetItem *item = currentItem(); + if (!item) return; + + QDrag *drag = new QDrag(this); + QMimeData *mimeData = new QMimeData; + + QString type = item->data(Qt::UserRole).toString(); + mimeData->setData("application/x-component", type.toUtf8()); + drag->setMimeData(mimeData); + + drag->setPixmap(item->icon().pixmap(iconSize())); + drag->setHotSpot(drag->pixmap().rect().center()); + + drag->exec(Qt::CopyAction); + } +}; + +#endif // MYLISTWIDGET_H