Qt/C++ 基于 QGraphicsView 的绘图软件 (附源码下载链接)

基于 Qt 的 QGraphicsView 绘图软件项目进行深入讲解,分析其核心代码与功能实现,帮助开发者理解 QGraphicsView 的用法。


项目概览

该项目实现了一个简单的绘图应用,用户可以在界面中创建和编辑矩形、椭圆、直线、多边形和文本等图形对象。功能包括添加图形、设置属性(颜色、字体)、移动、缩放、旋转、组合、删除等。


项目概览

通过网盘分享的文件:基于 QGraphicsView 的绘图软件
链接: https://pan.baidu.com/s/1g-thPifZmPKhLHJ8KFoL2w?pwd=jkcf 提取码: jkcf

核心代码讲解

1. 初始化与场景设置

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 创建 QGraphicsScene,并设置范围scene = new QGraphicsScene(-300, -200, 600, 400);// 将场景绑定到视图ui->View->setScene(scene);// 设置鼠标样式和拖拽模式ui->View->setCursor(Qt::CrossCursor);ui->View->setMouseTracking(true);ui->View->setDragMode(QGraphicsView::RubberBandDrag);// 初始化状态栏信息labViewCord = new QLabel(tc("View 坐标:"));labSceneCord = new QLabel(tc("Scene 坐标:"));labItemCord = new QLabel(tc("Item 坐标:"));labItemInfo = new QLabel(tc("ItemInfo: "));ui->statusBar->addWidget(labViewCord);ui->statusBar->addWidget(labSceneCord);ui->statusBar->addWidget(labItemCord);ui->statusBar->addWidget(labItemInfo);
}
  • QGraphicsScene:定义绘图区域,设置范围为 (-300, -200) 到 (300, 200)。
  • QGraphicsView:作为窗口的显示组件,绑定场景 scene,支持鼠标拖拽和实时追踪。
  • 状态栏:显示鼠标坐标、选中项的信息,便于交互。

2. 鼠标事件处理

鼠标移动事件
void MainWindow::on_mouseMovePoint(QPoint point)
{labViewCord->setText(tc("View 坐标:%1,%2").arg(point.x()).arg(point.y()));QPointF pointScene = ui->View->mapToScene(point);labSceneCord->setText(tc("Scene 坐标:%1,%2").arg(pointScene.x()).arg(pointScene.y()));
}
  • 获取鼠标的视图坐标,并将其转换为场景坐标,通过状态栏实时显示。
鼠标单击事件
void MainWindow::on_mouseClicked(QPoint point)
{QPointF pointScene = ui->View->mapToScene(point);QGraphicsItem *item = scene->itemAt(pointScene, ui->View->transform());if (item != nullptr){QPointF pointItem = item->mapFromScene(pointScene);labItemCord->setText(tc("Item 坐标:%1,%2").arg(pointItem.x()).arg(pointItem.y()));labItemInfo->setText(item->data(ItemDesciption).toString() + tc(", ItemId=") +item->data(ItemId).toString());}
}
  • 根据鼠标位置获取场景坐标,并检测该位置的绘图项。
  • 如果有绘图项,显示其局部坐标和描述信息(ItemIdItemDescription)。
鼠标双击事件
void MainWindow::on_mouseDoubleClick(QPoint point)
{QPointF pointScene = ui->View->mapToScene(point);QGraphicsItem *item = scene->itemAt(pointScene, ui->View->transform());if (item == nullptr) return;switch (item->type()){case QGraphicsRectItem::Type: // 矩形{QGraphicsRectItem *theItem = qgraphicsitem_cast<QGraphicsRectItem*>(item);setBrushColor(theItem);break;}case QGraphicsEllipseItem::Type: // 椭圆{QGraphicsEllipseItem *theItem = qgraphicsitem_cast<QGraphicsEllipseItem*>(item);setBrushColor(theItem);break;}case QGraphicsTextItem::Type: // 文本{QGraphicsTextItem *theItem = qgraphicsitem_cast<QGraphicsTextItem*>(item);QFont font = QFontDialog::getFont(nullptr, theItem->font(), this, tc("设置字体"));if (font.isValid())theItem->setFont(font);break;}}
}
  • 鼠标双击弹出对话框,根据绘图项类型设置填充颜色或字体。
  • 使用 qgraphicsitem_castQGraphicsItem 转换为具体类型。

3. 添加绘图项

添加矩形
void MainWindow::on_actItem_Rect_triggered()
{QGraphicsRectItem *item = new QGraphicsRectItem(-50, -25, 100, 50);item->setFlags(QGraphicsItem::ItemIsMovable |QGraphicsItem::ItemIsSelectable |QGraphicsItem::ItemIsFocusable);item->setBrush(QBrush(Qt::yellow));item->setZValue(++frontZ);scene->addItem(item);
}
  • 使用 QGraphicsRectItem 创建矩形。
  • 设置属性:
    • 可移动、可选中、可聚焦。
    • 填充颜色为黄色,Z 值递增(调整叠放顺序)。
添加文本
void MainWindow::on_actItem_Text_triggered()
{QString str = QInputDialog::getText(this, tc("输入文字"), tc("请输入文字"));if (str.isEmpty()) return;QGraphicsTextItem *item = new QGraphicsTextItem(str);QFont font = this->font();font.setPointSize(20);font.setBold(true);item->setFont(font);scene->addItem(item);
}
  • 使用 QGraphicsTextItem 创建文本,用户通过对话框输入文字。
  • 设置字体大小为 20,并加粗。

4. 操作绘图项

删除选中项
void MainWindow::on_actEdit_Delete_triggered()
{int cnt = scene->selectedItems().count();for (int i = 0; i < cnt; i++){QGraphicsItem *item = scene->selectedItems().at(0);scene->removeItem(item);}
}
  • 遍历选中项列表,逐个从场景中删除。
缩放与旋转
void MainWindow::on_actZoomIn_triggered()
{ui->View->scale(1.1, 1.1); // 放大视图
}void MainWindow::on_actRotateLeft_triggered()
{ui->View->rotate(-30); // 逆时针旋转视图
}
  • 放大视图的比例(scale)。
  • 顺时针/逆时针旋转视图(rotate)。
组合与解除组合
void MainWindow::on_actGroup_triggered()
{QGraphicsItemGroup *group = new QGraphicsItemGroup;scene->addItem(group);foreach (QGraphicsItem *item, scene->selectedItems()){group->addToGroup(item);}
}void MainWindow::on_actGroupBreak_triggered()
{QGraphicsItemGroup *group = qgraphicsitem_cast<QGraphicsItemGroup *>(scene->selectedItems().at(0));scene->destroyItemGroup(group);
}
  • 使用 QGraphicsItemGroup 将多个绘图项组合,方便整体操作。
  • 使用 destroyItemGroup 解除组合。

总结

该项目通过 Qt 提供的 QGraphicsView 框架,实现了一个简单但功能丰富的绘图软件。其核心功能包括:

  1. 绘图功能:支持矩形、椭圆、多边形、文本等图形的添加与属性设置。
  2. 交互功能:支持鼠标操作、移动、缩放、旋转等。
  3. 编辑功能:支持组合、解除组合、删除、层次调整。

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

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

相关文章

Vue2+OpenLayers给2个标点Feature分别添加独立的点击事件(提供Gitee源码)

前言&#xff1a;之前开发都是将所有的点位存放在一个图层上面&#xff0c;并统一赋予它们相同的点击事件&#xff0c;如果其中某些点的点击事件不一样呢&#xff0c;这种问题如何解决呢&#xff0c;本篇博客就是解决这个通点。 目录 一、案例截图 二、安装OpenLayers库 三…

山石防火墙命令行配置示例

现网1台山石SG6000防火墙&#xff0c;配置都可以通过GUI实现。 但有一些配置在命令行下配置效率更高&#xff0c;比如在1个已有策略中添加1个host或端口。 下面的双引号可以不加 1 创建服务 1.1 单个端口 service "tcp-901"tcp dst-port 901 1.2 端口范围 servi…

李宏毅机器学习课程笔记03 | 类神经网络优化技巧

文章目录 类神经网络优化技巧局部最小值local minima 与 鞍点saddle pointSaddle Point 的情况更常见 Tips for training&#xff1a;Batch and MomentumSmall Batch vs Large Batch回顾&#xff1a;optimization优化 找到参数使L最小问题&#xff1a;为什么要用Batch&#xff…

K8s 集群 IP 地址管理指南(K8s Cluster IP Address Management Guide)

K8s 集群 IP 地址管理指南 概述 你是否在小型初创公司或大型企业工作&#xff0c;并正在为公司评估 Kubernetes&#xff1f;你可能正在考虑运行十几个或更多的 Kubernetes (K8s) 集群。你期望每个集群支持几百个 K8s 节点&#xff0c;每个节点可能有 50 到 100 个 K8s Pod。这…

鸿蒙-点击Notification通知并打开App的具体页面

意图通知 获取router事件中传递参数并跳转 目前点击通知消息打开应用的指定页面&#xff0c;通过为通知添加行为意图的方式。也就是在wants的parameters中设置自定义参数&#xff0c;然后在UIAbility的onNewWant或者onCreate方法中 解析配置的自定义参数信息判断跳转不同页面&a…

go语言实现UTF8与GB2312内码转换

使用Go语言做个UTF-8转GB2312的代码,输入utf-8编码的文本&#xff0c;输出转换后的国标编码的hex内码 package mainimport ("fmt""os""strings""golang.org/x/text/encoding/simplifiedchinese""golang.org/x/text/transform&quo…

使用AKTools本地部署AKShare财经数据接口库

使用AKTools部署AKShare财经数据接口库&#xff0c;AKShare的介绍见&#xff1a;基于 Python 的财经数据接口库&#xff1a;AKShare-CSDN博客 AKTools 是一款用于快速搭建 AKShare HTTP API 的工具&#xff0c;通过 AKTools 可以利用一行命令来启动 HTTP 服务&#xff0c;从而…

FreeType 介绍及 C# 示例

FreeType 是一个开源的字体渲染引擎&#xff0c;用于将字体文件&#xff08;如 TrueType、OpenType、Type 1 等&#xff09;转换为位图或矢量图形。它广泛应用于操作系统、图形库、游戏引擎等领域&#xff0c;支持高质量的字体渲染和复杂的文本布局。 FreeType 的核心功能 字体…

winform监听全局鼠标事件

如果您希望监听全局鼠标事件&#xff0c;即使在其他应用程序&#xff08;如浏览器或其他软件&#xff09;中按下鼠标按钮也能捕捉到这些事件&#xff0c;您需要使用低级别的Windows API钩子。WinForms本身并不直接支持全局事件监听&#xff0c;但通过调用Windows API&#xff0…

如何学习网络安全?有哪些小窍门?

学好网络安全其实没有所谓的捷径&#xff0c;也没有什么小窍门。 入门网络安全首先要有浓厚的学习兴趣&#xff0c;不然很容易就变成了从入门到放弃了。 其次要能静下心&#xff0c;踏踏实实的打好基础。如果你是零基础&#xff0c;建议从Web安全入手&#xff0c;课程难度相对…

测试工程师的linux 命令学习(持续更新中)

1.ls """1.ls""" ls -l 除文件名称外&#xff0c;亦将文件型态、权限、拥有者、文件大小等资讯详细列出 ls -l等同于 ll第一列共10位&#xff0c;第1位表示文档类型&#xff0c;d表示目录&#xff0c;-表示普通文件&#xff0c;l表示链接文件。…

C++实现设计模式---享元模式 (Flyweight)

享元模式 (Flyweight) 享元模式 是一种结构型设计模式&#xff0c;它通过共享对象来减少内存使用和对象创建的开销。当系统中有大量相似对象时&#xff0c;享元模式可以避免重复创建相同对象&#xff0c;从而节省内存。 意图 通过共享相同对象来减少内存消耗。用于系统中存在…

如何在gitlab cicd中实现每月10号上午执行

在 GitLab CI/CD 中&#xff0c;可以通过设置定时触发器&#xff08;Schedules&#xff09;和脚本中的时间判断逻辑结合&#xff0c;确保任务只在每月 10 号的上午运行。 以下是实现的步骤&#xff1a; 1. 设置定时触发器 GitLab 提供了 Schedules 功能&#xff0c;可以指定每…

K8S 亲和性与反亲和性 深度好文

今天我们来实验 pod 亲和性。官网描述如下&#xff1a; 假设有如下三个节点的 K8S 集群&#xff1a; k8s31master 是控制节点 k8s31node1、k8s31node2 是工作节点 容器运行时是 containerd 一、镜像准备 1.1、镜像拉取 docker pull tomcat:8.5-jre8-alpine docker pull nginx…

安装指南:LLaMA Factory、AutoGPTQ 和 vllm

安装指南&#xff1a;LLaMA Factory、AutoGPTQ 和 vllm 在本文中&#xff0c;我们将详细介绍如何安装 LLaMA Factory、AutoGPTQ 和 vllm&#xff0c;这些工具在大型语言模型&#xff08;LLMs&#xff09;和视觉语言模型&#xff08;VLMs&#xff09;的微调和量化中非常有用。我…

Nginx三种不同类型的虚拟主机(基于域名、IP 和端口)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; Nginx-从零开始的服务器之旅专栏&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年1月15日13点14分 目录 1. 基于域名的虚拟主机 …

解析OVN架构及其在OpenStack中的集成

引言 随着云计算技术的发展&#xff0c;虚拟化网络成为云平台不可或缺的一部分。为了更好地管理和控制虚拟网络&#xff0c;Open Virtual Network (OVN) 应运而生。作为Open vSwitch (OVS) 的扩展&#xff0c;OVN 提供了对虚拟网络抽象的支持&#xff0c;使得大规模部署和管理…

C#异步和多线程,Thread,Task和async/await关键字--12

目录 一.多线程和异步的区别 1.多线程 2.异步编程 多线程和异步的区别 二.Thread,Task和async/await关键字的区别 1.Thread 2.Task 3.async/await 三.Thread,Task和async/await关键字的详细对比 1.Thread和Task的详细对比 2.Task 与 async/await 的配合使用 3. asy…

doris:导入概览

Apache Doris 提供了多种导入和集成数据的方法&#xff0c;您可以使用合适的导入方式从各种源将数据导入到数据库中。Apache Doris 提供的数据导入方式可以分为四类&#xff1a; 实时写入&#xff1a;应用程序通过 HTTP 或者 JDBC 实时写入数据到 Doris 表中&#xff0c;适用于…

【Flink系列】9. Flink容错机制

9. 容错机制 在Flink中&#xff0c;有一套完整的容错机制来保证故障后的恢复&#xff0c;其中最重要的就是检查点。 9.1 检查点&#xff08;Checkpoint&#xff09; 9.1.1 检查点的保存 1&#xff09;周期性的触发保存 “随时存档”确实恢复起来方便&#xff0c;可是需要我…