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

文章目录

  • 本系列目录
  • 前言
  • 一、QDrag类介绍
    • 1、使用描述
    • 2、相关函数
  • 二、代码实现
  • 总结


本系列目录

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。

原创文章,转载请标明本文出处。

你可能感兴趣的:(Qt,qt,流程图,ui)