QT-可拖拉绘图工具

2023-12-19 12:44
文章标签 工具 qt 绘图 拖拉

本文主要是介绍QT-可拖拉绘图工具,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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 modehorizontalStickyMode = 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 pressedif ((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 stickyModeverticalStickyMode = 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 verticallyitem->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

这篇关于QT-可拖拉绘图工具的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/512202

相关文章

QT Creator配置Kit的实现示例

《QTCreator配置Kit的实现示例》本文主要介绍了使用Qt5.12.12与VS2022时,因MSVC编译器版本不匹配及WindowsSDK缺失导致配置错误的问题解决,感兴趣的可以了解一下... 目录0、背景:qt5.12.12+vs2022一、症状:二、原因:(可以跳过,直奔后面的解决方法)三、解决方

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

MySQL慢查询工具的使用小结

《MySQL慢查询工具的使用小结》使用MySQL的慢查询工具可以帮助开发者识别和优化性能不佳的SQL查询,本文就来介绍一下MySQL的慢查询工具,具有一定的参考价值,感兴趣的可以了解一下... 目录一、启用慢查询日志1.1 编辑mysql配置文件1.2 重启MySQL服务二、配置动态参数(可选)三、分析慢查

Qt中实现多线程导出数据功能的四种方式小结

《Qt中实现多线程导出数据功能的四种方式小结》在以往的项目开发中,在很多地方用到了多线程,本文将记录下在Qt开发中用到的多线程技术实现方法,以导出指定范围的数字到txt文件为例,展示多线程不同的实现方... 目录前言导出文件的示例工具类QThreadQObject的moveToThread方法实现多线程QC

基于Python实现进阶版PDF合并/拆分工具

《基于Python实现进阶版PDF合并/拆分工具》在数字化时代,PDF文件已成为日常工作和学习中不可或缺的一部分,本文将详细介绍一款简单易用的PDF工具,帮助用户轻松完成PDF文件的合并与拆分操作... 目录工具概述环境准备界面说明合并PDF文件拆分PDF文件高级技巧常见问题完整源代码总结在数字化时代,PD

Python按照24个实用大方向精选的上千种工具库汇总整理

《Python按照24个实用大方向精选的上千种工具库汇总整理》本文整理了Python生态中近千个库,涵盖数据处理、图像处理、网络开发、Web框架、人工智能、科学计算、GUI工具、测试框架、环境管理等多... 目录1、数据处理文本处理特殊文本处理html/XML 解析文件处理配置文件处理文档相关日志管理日期和

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3

基于Python实现简易视频剪辑工具

《基于Python实现简易视频剪辑工具》这篇文章主要为大家详细介绍了如何用Python打造一个功能完备的简易视频剪辑工具,包括视频文件导入与格式转换,基础剪辑操作,音频处理等功能,感兴趣的小伙伴可以了... 目录一、技术选型与环境搭建二、核心功能模块实现1. 视频基础操作2. 音频处理3. 特效与转场三、高

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、