Qt (高仿Visio)流程图组件开发(八) 流程图 鼠标拖动图元到场景(QGraphicsScene)创建


本系列目录

Qt (高仿Visio)流程图组件开发(一) 效果展示及基本开发框架构思
Qt (高仿Visio)流程图组件开发(二) 基本图元绘制 图元间连线绘制
Qt (高仿Visio)流程图组件开发(三) 图元基类如何定义,流程图多种图元类型实现
Qt (高仿Visio)流程图组件开发(四) 流程图 图元对齐 磁吸线功能
Qt (高仿Visio)流程图组件开发(五) 流程图 双击编辑图元内容实现
Qt (高仿Visio)流程图组件开发(六) 流程图 线图元 如何绘制曲线 连接线移除视口后无法显示
Qt (高仿Visio)流程图组件开发(七) 流程图 简单操作界面搭建
Qt (高仿Visio)流程图组件开发(八) 流程图 鼠标拖动图元到场景(QGraphicsScene)创建
Qt (高仿Visio)流程图组件开发(九) 流程图 代码展示


前言

  使用过Visio的都清楚,其图元可以通过拖动的方式创建到场景中。从QT的视角来开就是把一个图元对象从一个QWidget控件拖动创建到场景中,这里使用QDrag类进行实现。


一、QDrag类介绍

1、使用描述

1、拖放是用户在应用程序中复制或移动数据的一种直观方式,并且在许多桌面环境中用作在应用程序之间复制数据的机制。
2、Qt中的拖放支持以QDrag类为中心,此类处理拖放操作的大多数细节。
3、通过拖放操作要传输的数据包含在QMimeData对象中。 通过setMimeData()指定:

     QDrag *drag = new QDrag(this);
     QMimeData *mimeData = new QMimeData;
 
     mimeData->setText(commentEdit->toPlainText());
     drag->setMimeData(mimeData);

4、setMimeData()将QMimeData对象的所有权分配给QDrag对象。必须在具有父QObject的堆上构造QDrag,以确保Qt在完成拖放操作后可以清理。
5、可以使用source()和target()找到源和目标小部件。这些功能通常用于确定拖放操作是否在同一窗口小部件上开始和结束,以便可以实现特殊行为。
该部分内容主要借鉴https://blog.csdn.net/kenfan1647/article/details/116089249,需要更清晰的学习使用,可以参考该博客。

2、相关函数

  • void QWidget::dragEnterEvent(QDragEnterEvent *event)
    当拖动正在进行并且鼠标进入此小部件时,将调用此事件处理程序。事件在事件参数中传递。
    如果忽略该事件,小组件将不会收到任何拖动移动事件。
  • void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
    当拖动正在进行并且鼠标离开此小组件时,将调用此事件处理程序。事件在事件参数中传递。
  • void QWidget::dragMoveEvent(QDragMoveEvent *event)
    如果正在进行拖动,并且发生以下任何情况时,将调用此事件处理程序:光标进入此小组件,光标在此小组件内移动,或者在此小组件具有焦点时按下键盘上的修饰键。事件在事件参数中传递。
  • void QWidget::dropEvent(QDropEvent *event)
    当拖放到此小组件上时,将调用此事件处理程序。事件在事件参数中传递。

二、代码实现

  点击按钮发送创建图元数据。

     void FlowCharToolSideBar::FlowButtonSlot()
    {
        QDrag *drag = new QDrag(this);
        QMimeData *data = new QMimeData();
        data->clear();
        QPushButton *clicked_btn = (QPushButton*)sender();
        if (clicked_btn == vec_btn_["流程"]){
            data->setText(QStringLiteral("流程"));
        }
        else if (clicked_btn == vec_btn_["判定"]){
            data->setText(QStringLiteral("判定"));
        }
        else if (clicked_btn == vec_btn_["自循环"]){
            data->setText(QStringLiteral("自循环"));
        }
        drag->setMimeData(data);
        drag->exec(Qt::MoveAction);
    }

  接收图元数据并创建。

    void FlowchartScene::dragEnterEvent(QGraphicsSceneDragDropEvent* event)
    {
        // ! [1] 判断是否接收数据
        if (event->source() == widget_) {
            event->ignore();
            return QGraphicsScene::dragEnterEvent(event);
        }
        flow_item_temp_ = nullptr;
        event->accept();

    }

    void FlowchartScene::dragMoveEvent(QGraphicsSceneDragDropEvent* event)
    {
        if (flow_item_temp_ == nullptr) {
            // ! [1] 创建对应图元类型
            QString item_type = event->mimeData()->text();
            FlowchartInforBase* item_infor = new FlowchartInforBase();
            if (item_type.compare(QStringLiteral("流程")) == 0)
            {
                item_infor->item_content_.content_ = QStringLiteral("算法流程");
                flow_item_temp_ = AddChildItem(item_infor, ItemType::Rect);
            }
            if (item_type.compare(QStringLiteral("判定")) == 0)
            {
                item_infor->item_content_.content_ = QStringLiteral("判定");
                flow_item_temp_ = AddChildItem(item_infor, ItemType::Condition);
            }
            if (item_type.compare(QStringLiteral("自循环")) == 0)
            {
                item_infor->item_content_.content_ = QStringLiteral("自循环");
                flow_item_temp_ = AddChildItem(item_infor, ItemType::Circulation);
            }
        }
        if (flow_item_temp_ == nullptr)
            return;
        FlowToQGraph(flow_item_temp_)->setPos(event->scenePos().toPoint());
    }

    void FlowchartScene::dragLeaveEvent(QGraphicsSceneDragDropEvent* event)
    {
        if (flow_item_temp_ != nullptr)
        {
            QGraphicsItem* item = FlowToQGraph(flow_item_temp_);
            this->removeItem(item);
            delete item;
            item = nullptr;
        }
    }

    void FlowchartScene::dropEvent(QGraphicsSceneDragDropEvent* event)
    {
        if (event->source() == widget_) {
            event->ignore();
            return QGraphicsScene::dragEnterEvent(event);
        }
        flow_item_temp_ = nullptr;
        event->acceptProposedAction();
    }

总结

本文为优化实现,酌情取用。
本文只是经验分享,描述内容并不绝对,如有误差欢迎指正。

如果此文帮助到你( •̀ ω •́ )✧,动动小手点个赞可好O(∩_∩)O。

原创文章,转载请标明本文出处。
  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的例子,演示如何在Qt中使用鼠标进行拖动绘图和连接图元连线。 ``` // MainWindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QGraphicsScene> #include <QGraphicsView> class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: QGraphicsScene *m_scene; QGraphicsView *m_view; bool m_isDrawing; QPointF m_lastPos; void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); }; #endif // MAINWINDOW_H ``` ``` // MainWindow.cpp #include "MainWindow.h" #include <QDebug> #include <QGraphicsEllipseItem> #include <QGraphicsLineItem> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), m_scene(new QGraphicsScene(this)), m_view(new QGraphicsView(m_scene, this)), m_isDrawing(false) { setCentralWidget(m_view); } MainWindow::~MainWindow() { } void MainWindow::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { if (m_isDrawing) { m_isDrawing = false; } else { m_isDrawing = true; // 创建一个圆形图元并添加到场景中 QGraphicsEllipseItem *item = new QGraphicsEllipseItem(event->pos().x(), event->pos().y(), 10, 10); m_scene->addItem(item); // 记录最后一个点的位置 m_lastPos = item->pos(); } } } void MainWindow::mouseMoveEvent(QMouseEvent *event) { if (m_isDrawing) { // 更新圆形图元的位置 QGraphicsEllipseItem *item = new QGraphicsEllipseItem(event->pos().x(), event->pos().y(), 10, 10); m_scene->addItem(item); // 创建一条线段连接前一个点和当前点,并添加到场景中 QGraphicsLineItem *line = new QGraphicsLineItem(m_lastPos.x() + 5, m_lastPos.y() + 5, event->pos().x() + 5, event->pos().y() + 5); m_scene->addItem(line); // 记录最后一个点的位置 m_lastPos = item->pos(); } } void MainWindow::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_isDrawing = false; } } ``` 在这个例子中,我们使用QGraphicsScene和QGraphicsView来显示图形。在mousePressEvent方法中,如果鼠标左键按下,我们创建一个圆形图元并将其添加到场景中。我们还记录最后一个点的位置。在mouseMoveEvent方法中,如果我们正在绘制,我们更新圆形图元的位置,并创建一条连接前一个点和当前点的线段,并将其添加到场景中。在mouseReleaseEvent方法中,如果鼠标左键释放,则停止绘制。 注意:该例子仅为演示如何在Qt中使用鼠标进行拖动绘图和连接图元连线。实际应用中,可能需要更复杂的逻辑和算法来实现更高级的绘图和连接图元功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦醒梦起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值