commit 0a6c228ec24c0be5bef3eccd40b017381d47c177 Author: lipengpeng Date: Wed Aug 6 08:38:38 2025 +0800 基本的界面,可以进行组件的拖拽 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