Qt 自定义流程图 diagram

2023-05-16

Qt 自定义流程图 diagram

  • 前言
    • 程序执行效果
    • 程序源码下载
    • 图形视图框架成员介绍
    • 重写QGraphicsItem
    • 程序源码介绍
    • 重点代码

前言

本文将对QGraphicsScene, QGraphicsView,QGraphicsItem这三个类进行简单介绍,并通过diagram流程图项目对自定义QGraphicsItem操作进行演示讲解。

程序执行效果

程序主界面
在这里插入图片描述
添加步骤

在这里插入图片描述
步骤删除
在这里插入图片描述
步骤连接
在这里插入图片描述
一键排序
在这里插入图片描述

程序源码下载

gitee

https://gitee.com/jiang_bin_yu/qt-diagram-jby

csdn

https://download.csdn.net/download/qq_37373742/87376898

图形视图框架成员介绍

QGraphicsScene, QGraphicsView,QGraphicsItem,分别是场景、视图和图元
1、场景:
QGraphicsScene场景类完成如下功能:

  • 提供管理大量图元的快速接口
  • 传播事件给场景中的每个图元
  • 管理图元状态,如选择和焦点处理
  • 提供无变换的绘制功能,如打印

2、视图:
QGraphicsView是视图窗口控件, 它使场景的内容可视化。可以连接几个视图到一个场景,也可以为相同的数据集提供几种不同的视口,
QGraphicsView是可滚动的窗口部件,如果需要使用OpenGL,使用QGrphicsView::setViewPort()将视口设置为QGLWidget。
视图接收键盘和鼠标的输入事件,并把它翻译为场景事件(将坐标转换为场景的坐标),使用变换矩阵函数QGraphicsView::matrix()
可以变换场景的坐标,通过这种方法尅实现场景缩放和旋转。QGraphicsView::mapToScene()和QGraphicsView::mapFromScene()将
视图和场景的坐标进行转换。

3、图元:
QGraphicsItem是图元基类,QGraphics View框架提供了几种标准的图元。
如QGraphicsRectItem、QGraphicsEllipseItem,QGraphicsTextItem等,可以继承QGraphicsItem实现符合自己需要的图元。
QGraphicsItem功能:

  • 处理鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件
  • 处理键盘输入事件
  • 处理拖放事件
  • 分组
  • 碰撞检测

重写QGraphicsItem

要编写自己的图形项,首先要创建QGraphicsItem的子类,然后从实现它的两个纯虚拟公共函数开始:
**boundingRect()**它返回该项绘制的区域的估计值
**paint()**实现实际绘制。
QGraphicsScene基于boundingRect()建立其项索引,QGraphicsView使用它来剔除不可见项,以及确定绘制重叠项时需要重新编译的区域。此外,QGraphicsItem的碰撞检测机制使用boundingRect()提供有效的截止点
QGraphicScene希望所有boundingRect()和shape()项保持不变,除非通知它。如果要以任何方式更改项的几何图形,必须首先调用prepareGeometryChange()以允许QgraphicsScene更新其记账。

程序源码介绍

在这里插入图片描述
图元:arrow 继承父类 QGraphicsLineItem 功能:绘制步骤箭头
图元:DiagramPixmapItem 继承父类 QGraphicsPixmapItem 功能:功能按钮/流程按钮图元
视图:DiagramView 继承父类QGraphicsView
场景:DiagramScene 继承父类 QGraphicsScene 功能:管理场景内图元

重点代码

实例化功能图元和步骤图元并放在在指定位置

 //功能栏
    for(int i=0; i<4; i++)
    {
        setMode(DiagramScene::InsertItem);

        DiagramPixmapItem* item = new DiagramPixmapItem(m_itemPix.at(i),m_itemName.at(i),QSize(107,157),true);
        QPointF point = QPointF(0+(item->pixmap().width()+27)*i,20);
        connect(item,&DiagramPixmapItem::ItemIsPressed,this,&DiagramScene::slot_itemSelect);

        addItem(item);
        item->setPos(point);
        vParentItems.append(item);
    }
    //步骤栏
    for(int i=4; i<7; i++)
    {
        setMode(DiagramScene::InsertItem);

        DiagramPixmapItem* item = new DiagramPixmapItem(m_itemPix.at(i),m_itemName.at(i),QSize(107,157),true);
        QPointF point = QPointF(0,(item->pixmap().height()+item->getTextHeight()+27)*(i-2)-77);
        connect(item,&DiagramPixmapItem::ItemIsPressed,this,&DiagramScene::slot_itemSelect);

        addItem(item);
        item->setPos(point);
        vParentItems.append(item);
    }

在这里插入图片描述

设置当前功能

功能包含:
InsertItem 插入步骤图元
InsertLine 插入连接箭头图元
MoveItem 移动图元
DeleteItem  删除图元
 enum Mode { InsertItem, InsertLine, MoveItem,DeleteItem };
 //设置当前功能
 void DiagramScene::setMode(Mode mode)
{
    myMode = mode;
}

根据点击功能栏的功能图元执行相应动作

//设置下一次将要添加的步骤
void DiagramScene::slot_itemSelect()
{
    currentSelectItem = (DiagramPixmapItem*)sender();
    if(currentSelectItem->getMyText() == "连接")
    {
        setMode(DiagramScene::InsertLine);
    }
    else if(currentSelectItem->getMyText() == "删除")
    {
        setMode(DiagramScene::DeleteItem);
    }
    else if(currentSelectItem->getMyText() == "移动")
    {
        setMode(DiagramScene::MoveItem);
    }
    else if(currentSelectItem->getMyText() == "一键排序")
    {
        qDebug() << "一键排序";
        setMode(DiagramScene::MoveItem);
        QList<DiagramPixmapItem*> newSortItems;    //根据箭头从新排序
        DiagramPixmapItem* firstItem = nullptr;       //最开始的流程
        //找到最开始的流程
        for(int i=0; i<vEditItems.size(); i++)
        {
            if(vEditItems.at(i)->getArrowSize() == 1)
            {
                Arrow* m_arrow = vEditItems.at(i)->getArrow().at(0);
                if(m_arrow->startItem() == vEditItems.at(i))
                {
                    firstItem = vEditItems.at(i);
                    qDebug() << "开始流程是" << vEditItems.at(i)->getMyText();
                }
            }
        }
        if(firstItem != nullptr)
        {
            SortPixmapItemByArrow(firstItem,&newSortItems); //根据箭头方向按顺序添加item
            //将无箭头的item 添加到 newSortItems后面
            foreach (DiagramPixmapItem* p, vEditItems) {
                if(p->getArrowSize() == 0)
                    newSortItems.append(p);
            }
            vEditItems = newSortItems;
        }

        //根据箭头方向排序
        for(int i=0; i<vEditItems.size(); i++)
        {
            if(i<vPosition.size())
                vEditItems.at(i)->setPos(vPosition.at(i));
        }
    }
    else
        setMode(DiagramScene::InsertItem);
}

通过鼠标事件完成 图元插入 图元连接 图元删除等功能


void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    //qDebug() << "press pos" << mouseEvent->scenePos();
    if (mouseEvent->button() != Qt::LeftButton)
        return;
    DiagramItem *item;
    switch (myMode) {
    case InsertItem:{
        if(mouseEvent->scenePos().x() < 200)
        {
            setMode(MoveItem);
            qDebug() << "步骤选择区,不能添加步骤";
            return QGraphicsScene::mousePressEvent(mouseEvent);
        }
        DiagramPixmapItem* item = new DiagramPixmapItem(currentSelectItem->getMyPixmapPath(),currentSelectItem->getMyText(),QSize(107,157));
        connect(item,&DiagramPixmapItem::ItemIsPressed,this,&DiagramScene::slot_itemSelect);
        item->setPos(mouseEvent->scenePos());
        addItem(item);
        vEditItems.append(item);
        if(vEditItems.size() >= 2)
        {
            line = new QGraphicsLineItem(QLineF(vEditItems.at(vEditItems.size()-2)->scenePos(),
                                                vEditItems.at(vEditItems.size()-1)->scenePos()));
            line->setPen(QPen(myLineColor, 2));
        }
        addItem(line);
        autoAddArrow();
        //qDebug() << "insert item at: " << mouseEvent->scenePos();
        hasItemSelected = itemAt(mouseEvent->scenePos(), QTransform()) != nullptr;
        setMode(MoveItem);
        clearAllSelectParentItem();
        break;
    }
    case InsertLine:
    {
        if (itemAt(mouseEvent->scenePos(), QTransform()) == nullptr) break;//绘制线的起始点 没有落在item上则无效
        //父类Item 不画线
        DiagramPixmapItem *pixItem = qgraphicsitem_cast<DiagramPixmapItem *>(itemAt(mouseEvent->scenePos(), QTransform()));
        if(pixItem->isParentFlag())
            return QGraphicsScene::mousePressEvent(mouseEvent);

        line = new QGraphicsLineItem(QLineF(mouseEvent->scenePos(),
                                            mouseEvent->scenePos()));
        line->setPen(QPen(myLineColor, 2));
        addItem(line);
        break;
    }
    case DeleteItem:
    {
        hasItemSelected = itemAt(mouseEvent->scenePos(), QTransform()) != nullptr;
        if(hasItemSelected)
        {
            deleteItems(QList<QGraphicsItem*>() << itemAt(mouseEvent->scenePos(), QTransform()));
        }
        break;
    }
    default:
        hasItemSelected = itemAt(mouseEvent->scenePos(), QTransform()) != nullptr;
    }
    QGraphicsScene::mousePressEvent(mouseEvent);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt 自定义流程图 diagram 的相关文章

  • 免费、便宜或开源的 UML 和类似 Visio 的工具 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 我们正在寻找免费 廉价或开
  • 用 UML 表示模板类的正确方法是什么?

    在 UML 图上 表示模板类的正确方法是什么 普通矩形右上角有一个虚线矩形 用来表示模板参数 像这样的东西 T ClassName
  • 使用Python或graphviz绘制鱼骨图

    我正在尝试用Python生成鱼骨图 因果图或石川图 有没有办法让它更像标准的鱼骨图 from graphviz import Digraph A HW Root SW Root Electric HW ink HW windows SW D
  • Uml / 序列 / 包 / ... JavaScript 和 Electron 应用程序的图表替代方案?

    我的问题是是否可以绘制任何类型的图表来可视化 Electron JavaScript 应用程序 我需要不同的 uml 图的替代方案 比如类或包图 但由于 JS 是基于原型的 它不像 Java 或 C 我不知道我能做什么 我唯一能够制作的是序
  • 用于从 C++ 代码生成 UML 图的 Eclipse 插件

    有没有可以从 C 源代码生成 UML 类图的 eclipse 插件 这也不是 Eclipse 插件 而是Umbrello UML 建模器 http uml sourceforge net index php来自 KDE 的软件是开源的 我使
  • Python 中的桑基图

    有没有一个Python库可以生成桑基图 http en wikipedia org wiki Sankey diagram 我见过这个桑基图应用程序和库列表 http www sankey diagrams com sankey diagr
  • 将关系属性从 ER 图转换为 SQL

    目前我是第一次尝试掌握 SQL 所以我正在解决一些问题 这是一个示例数据库规范 学生 姓名 性别 课程 做项目 标题 每个项目都有 两名主管 姓名 性别 部门 所有学生都做一个项目 但并非所有项目都被接受 不止一名学生可以做同样的事情 项目
  • 程序逻辑的可视化表示

    我想通过图表来表示我的程序的逻辑 因为该程序非常复杂 我需要一种方法来向另一个人解释我的程序中发生某些事情的原因和方式 流程图是唯一的选择吗 在 UML 中 不同的图针对不同的事物 使用不同的方法 考虑到我们倾向于倾向于面向对象的方法 我将
  • 推荐一个适合偶尔使用的好的实体关系图构建工具? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 免费软件是一个优点 您能否用一句话描述一下为什么它应该足够适合偶尔使用 编辑 你可能会检查这个很酷link http www refere
  • JavaScript 中的桑基图

    我想画一个桑基图 http en wikipedia org wiki Sankey diagram使用 JavaScript 任何人都可以提供一些有关可用于此的算法或库的指导吗 如果对其他人有帮助 我在这里提取了我的 javascript
  • 使用 Visio 2010 (Professional Plus) 从 SQL 导出实体关系图

    我正在寻找问题的相反解决方案从 Visio 图表导出 SQL https stackoverflow com questions 3506012 exporting sql from a viso diagram 我有用于创建 MySQL
  • 模板继承的 UML 图

    在我的库的文件中 我有一个继承自模板的类 我的代码示例 class data class dataA public data class dataB public data inheritance from a template templ
  • 从现有架构生成表关系图(SQL Server)[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有没有办法生成一个图表 显示现有表及其与数据库的连接的关系 这是针对 SQL Server 2008 Express Edition 的
  • 如何创建堆积线图

    在 R 中创建堆积条形图有多种解决方案 但如何绘制堆积线图呢 可以使用以下命令创建堆积线图ggplot2包裹 一些示例数据 set seed 11 df lt data frame a rlnorm 30 b 1 10 c rep LETT
  • Azure 数据工作室架构图?

    我最近刚刚下载了带有 SQL Server Express 的 Azure Data Studio 因为我使用的是 Linux 是否有实体关系图表功能 就像 SQL Server Management Studio 具有数据库图表功能一样
  • 如何用UML表示通信协议?

    在我的 UML 模型中 我有一个系统及其相互通信的子组件 例如 我有一台计算机和一个遥控机器人 它们通过蓝牙进行通信 目前图中的流程类似于 计算机 触发 遥控车 的 setVelocity 函数 在这一点上 我想通过说以下的话来完善沟通 计
  • 基于 C# .NET 文档的应用程序操作图

    我想开发一个新的应用程序 用户可以在其中创建描述流程的图表 我认为在这种情况下 基于文档的应用程序是我唯一的选择 我熟悉C net C MFC 和J2EE 根据您的经验 实现这一目标的最佳方法是什么 我应该关注哪个平台 图表必须由方框和箭头
  • 最容易实现的 Voronoi 图算法? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 实现 Voronoi 图的简单算法有哪些 我找不到任何专门以伪形式出现的算法 请分享一些 Vorono
  • 用于从某些标记生成 ASCII 图表的工具?

    有没有一种工具可以从某种标记生成 ASCII 图表 用例 能够快速创建和编辑可嵌入 javadoc 或任何其他注释 中的图表 类似于允许我们编写一些标记的内容 A HAS gt B B HAS gt C 该工具将生成可视化结果 A HAS
  • Matlab:条形图中缺少标签

    使用 Matlab 2012 和 2013 我发现设置XTickLabel on a bar图表最多只能使用 15 个柱 如果条形较多 则标签会丢失 如下所示 绘制 15 个条形图 N 15 x 1 N labels num2str x d

随机推荐

  • 在头文件实现函数的重定义问题

    例如一个头文件headfile h这样写 pragma once bool Func return true 在这个头文件被多个地方包含的时候就会出问题 xff0c 链接时报错 FuncB报重定义 fatal error LNK1169 找
  • 数字电路基础知识系列(六)之LC滤波器的基础知识

    针对设计过程的问题 xff0c 如有疑问 xff0c 欢迎留言讨论 xff01 点我返回目录 LC滤波器 xff0c 是指将电感 L 与电容器 进行组合设计构成的滤波电路 xff0c 可去除或通过特定频率的无源器件 电容器具有隔直流通交流
  • I-002 智能家居系列--ESP8266环境搭建

    智能家居系列 1 NodeMCU简介2 硬件介绍3 开发工具的选择3 1 软件介绍3 2 环境搭建 4 测试代码5 后续会更新这边文章 1 NodeMCU简介 NodeMCU简介 NodeMCU 是一个开源的 物联网 平台 它使用 Lua
  • I-000 智能家居系列--需求梳理

    智能家居系列 1 智能家居2 系统框架3 组成部分4 开发思路5 当前的进展 1 智能家居 智能家居的目的旨在提高人们的生活水平 xff0c 确保人们的生活更加舒适 2 系统框架 下图只是初版 xff0c 在具体的开发过程中 xff0c 会
  • Cartographer(二)使用思岚rplidar雷达进行cartographer建图

    一 修改launch文件和lua配置文件 xff08 1 xff09 修改revo lds lua 到目录下 xff0c 打开文件 home meng xx catographer ws src cartographer ros carto
  • 数字电路硬件设计系列(三)之缓启电路设计

    针对设计过程中的问题 xff0c 如有疑问 xff0c 欢迎留言评论 xff01 点我返回目录 1 简介 在一些大电压 大电流的产品中 xff0c 上电的瞬间通常会有较大的电流冲击 xff0c 下图是一款产品上电过程中波形 最大的电流达到1
  • 数字电路硬件设计系列(十)之RS485电路设计

    针对设计过程中的问题 xff0c 如有疑问 xff0c 欢迎留言评论 xff01 点我返回目录 1 简介 RS485通信属于串口通信中的半双工通信 xff0c RS485具有支持多节点 xff08 32个节点 xff09 传输距离远 xff
  • 数字电路硬件设计系列(五)之AT89C51/C52最小系统设计

    针对设计过程中的问题 xff0c 如有疑问 xff0c 欢迎留言评论 xff01 点我返回目录 1 简介 AT89C51 C52是指两个系列的产品 xff0c 具体包含AT89C51 AT89C52 xff0c 但是最小系统的组成基本上相差
  • 1.18 接地设计问题(非常实用)

    目录 1 简介 2 接地的分类 3 接地的目的 3 1 对地阻抗低 3 2 地平面稳定 3 3 对地均衡 4 共地耦合干扰 5 常用的基地方式 6 安全地 防雷击浪涌接地的接法 1 简介 在电路设计的过程中 xff0c 接地是一个老生常谈的
  • 1.0 硬件设计基础(面试题)

    1 滤波磁珠和滤波电感的区别 磁珠由导线穿过铁氧体组成 xff0c 直流电阻很小 xff0c 在低频时阻抗也很小 xff0c 对直流信号几乎没有影响 在高频 xff08 几十兆赫兹以上 xff09 时磁珠阻抗比较大 xff0c 高频电磁场在
  • 1.19 旁路电容与去耦电容

    1 简介 旁路电容和旁路电容是电路设计过程中十分常见 xff0c 但是很多应将工程师都没有真正区分这两者的功能 xff0c 我们先来看看这两个单词在英文中的意思 xff1a 电容英文中文解释旁路电容Bypass抄近道去耦电容couple是一
  • vins运行1

    vins fusion 运行笔记 安装code utils 1 fatal error elfutils libdw h 没有那个文件或目录 没有安装 sudo apt get install libdw dev 2 fatal error
  • 四旋翼无人机汇报

    我主要负责的是四旋翼无人机的组装和飞控参数的调试 遇到的问题 当初焊接时由于时间紧张用的是比较细的焊条 xff0c 虽然焊接成功 xff0c 但是导致了后续插拔导线时容易接触不良 xff0c 后来在焊点处重新焊接 由于未在地面站软件中修改无
  • 载波相位差分定位

    x1f30e 我接触差分定位是通过暑期在南京北斗一段时间的实习 x1f30e 我把 Lambda算法的zip和rar上传到了这里 x1f30e https wwi lanzoui com b01bp70yj x1f30e 再推荐一个gith
  • nRF SPI 与 TWI 操作相关 (BMI088 与 MLX90614 举例)

    SPI0 与 TWI0 的 ID相同 xff0c SPI0 与 TWI0 的 ID相同 编译时有报错 若要避免 xff0c 有两个方法 1 使用不同ID外设 2 使用模拟SPI或模拟IIC nRF SPI 初始化 sdk config h
  • ros(13):ros找不到包报错及解决办法--Config.cmake

    目录 一 基础包 1 1 rospy包 1 2 tf包 1 3 grid map包 1 4 serial 二 专有包 2 1 dynamic reconfigure包 2 2 rosparam handler包 2 3 qt build包
  • stm32 esp8266 ota升级-自建mqtt和文件服务器动态AB面升级

    stm32 esp8266 ota系列文章 xff1a stm32 esp8266 ota 快速搭建web服务器之docker安装openresty stm32 esp8266 ota升级 tcp模拟http stm32 esp8266 o
  • win系统C++的udp通信(接收并发送)详细教程、win下inet_pton和inet_ntop无法使用解决方法

    对UDP编程0基础的可以参考这篇记录博文 我做的是同一个程序中接收指定IP地址和端口号的信息作为输入 xff0c 通过程序的算法进行处理 xff0c 处理后的信息再通过另一个指定IP地址和端口号进行发送 也就是需要做两个udp一个接收数据
  • postman下载与汉化(附直接下载链接)

    想用英文版本的可以直接点击如下链接下载最新版本 官网最新版本 无法汉化 xff1a Download Postman Get Started for Free 如果想要汉化的就不能使用最新版本 xff0c 因为最新版本没有汉化包可以用 汉化
  • Qt 自定义流程图 diagram

    Qt 自定义流程图 diagram 前言程序执行效果程序源码下载图形视图框架成员介绍重写QGraphicsItem程序源码介绍重点代码 前言 本文将对QGraphicsScene QGraphicsView QGraphicsItem这三个