QT-可拖拉绘图工具

news2024/12/25 9:35:05

QT-可拖拉绘图工具

  • 一、演示效果
  • 二、关键程序
  • 三、下载链接

一、演示效果

在这里插入图片描述

二、关键程序

#include "diagramscene.h"
#include "arrow.h"

#include <QTextCursor>
#include <QGraphicsSceneMouseEvent>
#include <QDebug>

QPen const DiagramScene::penForLines = QPen(QBrush(QColor(Qt::black)), 2, Qt::PenStyle::DashLine);

DiagramScene::DiagramScene(QMenu *itemMenu, QObject *parent)
    : QGraphicsScene(parent)
{
    myItemMenu = itemMenu;
    myMode = MoveItem;
    myItemType = DiagramItem::Step;
    line = nullptr;
    textItem = nullptr;
    myItemColor = Qt::white;
    myTextColor = Qt::black;
    myLineColor = Qt::black;
}

void DiagramScene::setLineColor(const QColor &color)
{
    myLineColor = color;
    foreach (QGraphicsItem* p, selectedItems()) {
        if (p->type() == Arrow::Type) {
            Arrow* item = qgraphicsitem_cast<Arrow*>(p);
            item->setColor(myLineColor);
            update();
        }
    }
}

void DiagramScene::setTextColor(const QColor &color)
{
    myTextColor = color;
    foreach (QGraphicsItem* p, selectedItems()) {
        if (p->type() == DiagramTextItem::Type) {
            DiagramTextItem* item = qgraphicsitem_cast<DiagramTextItem*>(p);
            item->setDefaultTextColor(myTextColor);
        }
    }
}
//! [2]

//! [3]
void DiagramScene::setItemColor(const QColor &color)
{
    myItemColor = color;
    foreach (QGraphicsItem* p, selectedItems()) {
        if (p->type() == DiagramItem::Type) {
            DiagramItem* item = qgraphicsitem_cast<DiagramItem*>(p);
            item->setBrush(myItemColor);
        }
    }
}

void DiagramScene::setFont(const QFont &font)
{
    myFont = font;
    foreach (QGraphicsItem* p, selectedItems()) {
        if (p->type() == DiagramTextItem::Type) {
            DiagramTextItem* item = qgraphicsitem_cast<DiagramTextItem*>(p);
            item->setFont(myFont);
        }
    }
}

void DiagramScene::deleteItems(QList<QGraphicsItem*> const& items) {
    qDebug() << "delete items" << items;

    QList<QGraphicsItem*> diagramItems;
    foreach (QGraphicsItem *item, items) {
        if (item->type() == Arrow::Type) {
            removeItem(item);
            Arrow *arrow = qgraphicsitem_cast<Arrow *>(item);
            arrow->startItem()->removeArrow(arrow);
            arrow->endItem()->removeArrow(arrow);
            delete item;
        } else diagramItems.append(item);
    }

    foreach (QGraphicsItem *item, diagramItems) {
        if (item->type() == DiagramItem::Type)
             qgraphicsitem_cast<DiagramItem *>(item)->removeArrows();
        removeItem(item);
        delete item;
    }
}
//! [4]

void DiagramScene::setMode(Mode mode)
{
    myMode = mode;
}

void DiagramScene::setItemType(DiagramItem::DiagramType type)
{
    myItemType = type;
}

//! [5]
void DiagramScene::editorLostFocus(DiagramTextItem *item)
{
    QTextCursor cursor = item->textCursor();
    cursor.clearSelection();
    item->setTextCursor(cursor);

    if (item->toPlainText().isEmpty()) {
        removeItem(item);
        item->deleteLater();
    } else {
        if (item->contentIsUpdated()) {
            qDebug() << "content update ---";
            emit textChanged();
        }
    }

}

void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    if (mouseEvent->button() != Qt::LeftButton)
        return;

    DiagramItem *item;
    switch (myMode) {
        case InsertItem:
            item = new DiagramItem(myItemType, myItemMenu);
            item->setBrush(myItemColor);
            addItem(item);
            item->setPos(mouseEvent->scenePos());
            qDebug() << "insert item at: " << mouseEvent->scenePos();
            qDebug() << "\ttype: " << myItemType << " color: " << myItemColor;
            emit itemInserted(item);
            hasItemSelected = itemAt(mouseEvent->scenePos(), QTransform()) != nullptr;
            break;

        case InsertLine:
            if (itemAt(mouseEvent->scenePos(), QTransform()) == nullptr) break;
            line = new QGraphicsLineItem(QLineF(mouseEvent->scenePos(),
                                        mouseEvent->scenePos()));
            line->setPen(QPen(myLineColor, 2));
            addItem(line);
            break;

        case InsertText:
            textItem = new DiagramTextItem();
            textItem->setFont(myFont);
            textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
            textItem->setZValue(1000.0);
            connect(textItem, SIGNAL(lostFocus(DiagramTextItem*)),
                    this, SLOT(editorLostFocus(DiagramTextItem*)));
            connect(textItem, SIGNAL(selectedChange(QGraphicsItem*)),
                    this, SIGNAL(itemSelected(QGraphicsItem*)));
            addItem(textItem);
            textItem->setDefaultTextColor(myTextColor);
            textItem->setPos(mouseEvent->scenePos());
            emit textInserted(textItem);
            qDebug() << "text inserted at" << textItem->scenePos();
            break;

    default:
        hasItemSelected = itemAt(mouseEvent->scenePos(), QTransform()) != nullptr;
    }
    QGraphicsScene::mousePressEvent(mouseEvent);
}

void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) {
    if (myMode == InsertLine && line != nullptr) {
        QLineF newLine(line->line().p1(), mouseEvent->scenePos());
        line->setLine(newLine);
    } else if (myMode == MoveItem) {
        if (hasItemSelected)
            mouseDraggingMoveEvent(mouseEvent);
        QGraphicsScene::mouseMoveEvent(mouseEvent);
    }
}

void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) {
    hasItemSelected = false;

    // leave sticky mode
    horizontalStickyMode = false;
    verticalStickyMode = false;
    foreach(QGraphicsItem* p, selectedItems())
        p->setFlag(QGraphicsItem::ItemIsMovable);

    clearOrthogonalLines();
    if (line != nullptr && myMode == InsertLine) {
        QList<QGraphicsItem *> startItems = items(line->line().p1());
        if (startItems.count() && startItems.first() == line)
            startItems.removeFirst();
        QList<QGraphicsItem *> endItems = items(line->line().p2());
        if (endItems.count() && endItems.first() == line)
            endItems.removeFirst();

        removeItem(line);
        delete line;

        if (startItems.count() > 0 && endItems.count() > 0 &&
            startItems.first()->type() == DiagramItem::Type &&
            endItems.first()->type() == DiagramItem::Type &&
            startItems.first() != endItems.first()) {
            DiagramItem *startItem = qgraphicsitem_cast<DiagramItem *>(startItems.first());
            DiagramItem *endItem = qgraphicsitem_cast<DiagramItem *>(endItems.first());
            Arrow *arrow = new Arrow(startItem, endItem);
            arrow->setColor(myLineColor);
            startItem->addArrow(arrow);
            endItem->addArrow(arrow);
            arrow->setZValue(-1000.0);
            addItem(arrow);
            arrow->updatePosition();
            emit arrowInserted();
        }
    }

    line = nullptr;
    QGraphicsScene::mouseReleaseEvent(mouseEvent);
}

void DiagramScene::wheelEvent(QGraphicsSceneWheelEvent* wheelEvent) {
    // ctrl key is being pressed
    if ((wheelEvent->modifiers() & Qt::KeyboardModifier::ControlModifier) != 0) {
        emit scaleChanging(wheelEvent->delta());
        wheelEvent->accept();
    } else {
        QGraphicsScene::wheelEvent(wheelEvent);
    }
}

void DiagramScene::mouseDraggingMoveEvent(QGraphicsSceneMouseEvent* event) {
    clearOrthogonalLines();
    if ((event->buttons() & Qt::LeftButton) != 0 && selectedItems().size() == 1) {
        QGraphicsItem* itemUnderCursor = selectedItems().first();
        QPointF curCenter = itemUnderCursor->scenePos();
        QPointF const& mousePos = event->scenePos();

        foreach(QGraphicsItem* p, items()) {
            if (p->type() != DiagramItem::Type || p == itemUnderCursor) continue;

            DiagramItem* item = qgraphicsitem_cast<DiagramItem*>(p);
            QPointF const& objPoint = item->scenePos();
            LineAttr lineAttr;

            tryEnteringStickyMode(itemUnderCursor, objPoint, mousePos);

            if ((lineAttr = getPointsRelationship(objPoint, curCenter)) != Other) {
                if ((lineAttr & Horizontal) != 0) {
                    QGraphicsLineItem* newHLine = new QGraphicsLineItem();
                    newHLine->setLine(QLineF(QPointF(0, objPoint.y()),
                                             QPointF(sceneRect().width(), objPoint.y())));
                    newHLine->setPen(penForLines);
                    orthogonalLines.append(newHLine);
                }
                if ((lineAttr & Vertical) != 0) {
                    QGraphicsLineItem* newVLine = new QGraphicsLineItem();
                    newVLine->setLine(QLineF(QPointF(objPoint.x(), 0),
                                             QPointF(objPoint.x(), sceneRect().height())));
                    newVLine->setPen(penForLines);
                    orthogonalLines.append(newVLine);
                }
            }
        }
        tryLeavingStickyMode(itemUnderCursor, mousePos);
    }
    foreach(QGraphicsLineItem* p, orthogonalLines) {
        addItem(p);
    }
}

void DiagramScene::clearOrthogonalLines() {
    foreach(QGraphicsLineItem* p, orthogonalLines) {
        removeItem(p);
        delete p;
    }
    orthogonalLines.clear();
}

bool DiagramScene::closeEnough(qreal x, qreal y, qreal delta) {
    return std::abs(x - y) < delta;
}

DiagramScene::LineAttr DiagramScene::getPointsRelationship(const QPointF& p1,
                                                           const QPointF& p2) {
    int ret = Other;
    ret |= closeEnough(p1.x(), p2.x(), Delta) ? Vertical : Other;
    ret |= closeEnough(p1.y(), p2.y(), Delta) ? Horizontal : Other;
    return static_cast<DiagramScene::LineAttr>(ret);
}

void DiagramScene::tryEnteringStickyMode(QGraphicsItem* item, const QPointF& target,
                                         const QPointF& mousePos) {
    QPointF const& itemPos = item->scenePos();
    if (!verticalStickyMode) {
        if (closeEnough(itemPos.x(), target.x(), stickyDistance)) {  // enter stickyMode
            verticalStickyMode = true;
            verticalStickPoint = mousePos;
            item->setFlag(QGraphicsItem::ItemIsMovable, false);
            item->setPos(QPointF(target.x(), itemPos.y()));
        }
    }
    if (!horizontalStickyMode) {
        if (closeEnough(itemPos.y(), target.y(), stickyDistance)) {
            horizontalStickyMode = true;
            horizontalStickPoint = mousePos;
            item->setFlag(QGraphicsItem::ItemIsMovable, false);
            item->setPos(QPointF(itemPos.x(), target.y()));
        }
    }
}

void DiagramScene::tryLeavingStickyMode(QGraphicsItem* item, const QPointF& mousePos) {
    if (verticalStickyMode) { // already in stickyMode, item should be able to move vertically
        item->moveBy(0, mousePos.y() - verticalStickPoint.y());
        verticalStickPoint.setY(mousePos.y());

        // when to exit stickyMode?
        if (!closeEnough(mousePos.x(), verticalStickPoint.x(), stickyDistance)) {
            verticalStickyMode = false;
            item->setFlag(QGraphicsItem::ItemIsMovable, true);
        }
    }
    if (horizontalStickyMode) {
        item->moveBy(mousePos.x() - horizontalStickPoint.x(), 0);
        horizontalStickPoint.setX(mousePos.x());

        if (!closeEnough(mousePos.y(), horizontalStickPoint.y(), stickyDistance)) {
            horizontalStickyMode = false;
            item->setFlag(QGraphicsItem::ItemIsMovable, true);
        }
    }
}


三、下载链接

https://download.csdn.net/download/u013083044/88640602

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1320157.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows本地搭建开源企业管理套件Odoo并实现公网访问

文章目录 前言1. 下载安装Odoo&#xff1a;2. 实现公网访问Odoo本地系统&#xff1a;3. 固定域名访问Odoo本地系统 前言 Odoo是全球流行的开源企业管理套件&#xff0c;是一个一站式全功能ERP及电商平台。 开源性质&#xff1a;Odoo是一个开源的ERP软件&#xff0c;这意味着企…

当OneNote不同步时,你需要做些什么让其恢复在线

OneNote笔记本无法同步的原因有很多。由于OneNote使用OneDrive将笔记本存储在云中,因此可能会出现互联网连接问题,与多人联机处理笔记本时会出现延迟,以及从不同设备处理同一笔记本时会发生延迟。以下是OneNote不同步时的操作。 注意:本文中的说明适用于OneNote for Windo…

什么是工业互联网平台?

1.什么是工业互联网平台&#xff1f; 1.1 工业互联网平台的定义 工业互联网平台是一个连接设备与服务、数据与人的跨行业、跨领域的全新工业平台。工业互联网平台利用了互联网、物联网、大数据、AI等技术&#xff0c;集成各类工业设备&#xff0c;不断采集和分析数据&#xff…

百度地图添加坐标点,并返回坐标信息

1、创建地图容器 在mounted中初始化地图、鼠标绘制工具和添加鼠标监听事件 vue data中添加地图和绘制工具对象 2、添加初始化化地图方法 initMap(longitude, latitude) {let that thisthat.map new BMapGL.Map("container");// 创建地图实例if (longitude null ||…

功放诊断测试

1.切换trace显示时间模式&#xff0c;Toggle time mode 2.测seedkey 需要加载seednkey.dll 3.功能寻址和物理寻址切换

idea恢复默认出厂设置

idea恢复默认出厂设置 1、IDEA 2021 之后&#xff0c; 在顶部工具栏&#xff0c;选择 File | Manage IDE Settings | Restore Default Settings. 2、或者双击shift搜索Restore Default settings然后点击restore and restart

MySQL安装——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

MySQLhttps://www.mysql.com/ 将下发的ds_db01.sql数据库文件放置mysql中 12、编写Scala代码&#xff0c;使用Spark将MySQL的ds_db01库中表user_info的全量数据抽取到Hive的ods库中表user_info。字段名称、类型不变&#xff0c;同时添加静态分区&#xff0c;分区字段为etl_da…

ubuntu18.04 64 位安装笔记——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

进入VirtuakBox官网&#xff0c;网址链接&#xff1a;Oracle VM VirtualBoxhttps://www.virtualbox.org/ 网页连接&#xff1a;Ubuntu Virtual Machine Images for VirtualBox and VMwarehttps://www.osboxes.org/ubuntu/ 将下发的ds_db01.sql数据库文件放置mysql中 12、编写S…

代码随想录算法训练营Day5 | 242.有效的字母异位词、349.两个数组的交集、202.快乐数、1. 两数之和

LeetCode 242 有效的字母异位词 本题思路&#xff1a;我们只需要分别统计&#xff0c;字符串 s ,字符串 t 中每个字符的出现次数&#xff0c;分别用两个数组来存储&#xff0c;然后再循环遍历对比两个数组中相同位置出现的次数&#xff0c;如果有不同的则返回 false。 统计完之…

双非大数据

双非本秋招上岸总结 个人简介 学历&#xff1a;双非&#xff1b; 专业&#xff1a;软件工程&#xff1b; 求职岗位&#xff1a;大数据开发工程师&#xff1b; 状态&#xff1a;已上岸 翻车经历 学校以Java后端开发为主流&#xff0c;我从大二开始学习Java&#xff0c;直到大四…

HarmonyOS(十四)——状态管理之@State装饰器(组件内状态)

前言 在初识状态管理我们了解了状态管理的基本概念&#xff0c;以及管理组件拥有的状态有哪几种装饰器&#xff0c;今天我们就来认识一下第一种装饰器&#xff1a;State装饰器&#xff08;组件内状态&#xff09;。 概述 State装饰的变量&#xff0c;或称为状态变量&#xf…

解决 Hbuilder打包 Apk pad 无法横屏 以及 H5 直接打包 成Apk

解决 Hbuilder打包 Apk pad 无法横屏 前言云打包配置 前言 利用VUE 写了一套H5 想着 做一个APP壳 然后把 H5 直接嵌进去 客户要求 在pad 端 能够操作 然后页面风格 也需要pad 横屏展示 云打包 配置 下面是manifest.json 配置文件 {"platforms": ["iPad"…

Vue--第十天

终极实战----大事件项目 1.简介&#xff1a; 2.创建项目&#xff1a; 1.创建&#xff08;159-163&#xff09;&#xff1a; 还是对着视频操作吧 2.路由&#xff1a; 3.element Plus: 导入element Plus 后不需要再导入插件配置&#xff0c;就连组件导入也不用 4.pinia构建用…

Ubuntu Desktop 22.04 设置 ssh 超时时间

Ubuntu Desktop 22.04 使用 ssh 连接服务器时&#xff0c;发现一段时间不操作就会自动断开连接&#xff0c;解决方法如下&#xff1a; 打开 /etc/ssh/ssh_config 文件&#xff1a; sudo vim /etc/ssh/ssh_config在文件最后添加&#xff1a; # ssh 客户端会每隔 30 秒发送一个…

网络(九)三层路由、DHCP以及VRRP协议介绍

目录 一、三层路由 1. 定义 2. 交换原理 3. 操作演示 3.1 图示 3.2 LSW1新建vlan10、20、30&#xff0c;分别对应123接口均为access类型&#xff0c;接口4为trunkl类型&#xff0c;允许所有vlan通过 3.3 LSW2新建vlan10、20、30&#xff0c;配置接口1为trunk类型&…

ElasticSearch单机或集群未授权访问漏洞

漏洞处理方法&#xff1a; 1、可以使用系统防火墙 来做限制只允许ES集群和Server节点的IP来访问漏洞节点的9200端口&#xff0c;其他的全部拒绝。 2、在ES节点上设置用户密码 漏洞现象&#xff1a;直接访问9200端口不需要密码验证 修复过程 2.1 生成认证文件 必须要生成…

JupyterHub 如何切换 conda 小环境

JupyterHub 如何切换 conda 小环境 服务器已经部署好 JupyterHub &#xff0c;相关端口请看对应答疑群群公告。在Jupyterhub 中使用 conda 创建的小环境&#xff0c;首先 ssh 登录上服务器或者在 JupyterHub 网页端打开终端 terminal。然后安装 conda &#xff0c;方法请见 Q4&…

动能方案 | 技术引领未来:两轮电动车遥控解锁方案探秘

随着电动交通工具的快速普及&#xff0c;创新性的智能解锁系统正在为两轮电动车带来更便捷、安全的使用体验。本文将深入介绍一种先进的两轮电动车遥控解锁方案&#xff0c;探讨其优势&#xff0c;并推荐一款先进的芯片技术&#xff0c;引领行业未来。 01方案介绍 1、技术原…

什么是tomcat?tomcat是干什么用的?

目录 Tomcat 的主要用途包括&#xff1a; 托管Java Web应用程序&#xff1a; Servlet 容器&#xff1a; 以下是关于Servlet容器的一些关键特性和功能&#xff1a; 生命周期管理&#xff1a; 多线程支持&#xff1a; HTTP请求处理&#xff1a; HTTP响应生成&#xff1a;…

《代码随想录》--二叉树(一)

《代码随想录》--二叉树 第一部分 1、二叉树的递归遍历2、二叉树的迭代遍历3、统一风格的迭代遍历代码4、二叉树的层序遍历226.翻转二叉树 1、二叉树的递归遍历 前序遍历 中序遍历 后序遍历 代码 前序遍历 class Solution {public List<Integer> preorderTraversal(T…