当前位置: 首页 > news >正文

Qt实现绘制自定义形状

先创建一个继承自QWidget的控件:

class MyPainterWidget:public QWidget

重写各种鼠标方法:

protected:void paintEvent(QPaintEvent *) override;void mousePressEvent(QMouseEvent *e) override;       //按下void mouseMoveEvent(QMouseEvent *e) override;        //移动void mouseReleaseEvent(QMouseEvent *e) override;     //松开void mouseDoubleClickEvent(QMouseEvent *event) override;

在构造函数中声明跟踪鼠标:

#include <QMouseEvent>
setMouseTracking(true);

定义两个标志位作为开始绘制和鼠标移动的标志:

bool m_bStartDraw = false;    //是否已经开始左键点击,同时标识是否开始进行绘制bool bMove = false;           //是否处于绘制时的鼠标移动状态

创建一个点集记录每次按下的坐标点:

QVector<QPointF> pointList;

在程序一开始的时候先清除点集:

MyPainterWidget::MyPainterWidget(QWidget *parent) : QWidget(parent)
{setMouseTracking(true);pointList.clear();
}

按下鼠标时将开始绘制标志位设为true:

// 按下
void MyPainterWidget::mousePressEvent(QMouseEvent *e)
{if (e->button() == Qt::LeftButton){if(!m_bStartDraw){pointList.clear();m_bStartDraw = true;}}   
}

创建一个点用于获取鼠标移动时的当前位置:

QPointF movePoint;

重写移动事件:

// 移动
void MyPainterWidget::mouseMoveEvent(QMouseEvent *e)
{if(m_bStartDraw){movePoint = e->pos();this->update();//重新进入painEvent事件进行绘制// 先刷新再设为true, 防止第一点和(0,0)连在一块bMove = true;}
}

重写释放事件:

// 松开
void MyPainterWidget::mouseReleaseEvent(QMouseEvent *e)
{if (e->button() == Qt::LeftButton){if (m_bStartDraw){// 鼠标松开后的点需要添加到路径中pointList.push_back(QPointF(e->x(), e->y()));bMove = false;this->update();//刷新绘制}}
}

写一个表示结束绘制的功能函数:

void MyPainterWidget::endDraw()
{m_bStartDraw = false;//需要把第一个点连起来pointList.push_back(pointList[0]);this->update();
}

实现清除所有已绘的功能函数:

void MyPainterWidget::clearPath()
{pointList.clear();this->update();
}

主窗口:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QMenu>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();protected:// 右键菜单需要重写的类void contextMenuEvent(QContextMenuEvent* event) override;private:Ui::MainWindow *ui;QMenu* m_pMenu;
};
#endif // MAINWINDOW_H
/*使用方式左键点击,移动鼠标开始绘制,双击左键结束绘制,或者右键点击结束绘制*/#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenu>
#include <QAction>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);m_pMenu = new QMenu(this);QAction* pAc1 = new QAction(QString::fromLocal8Bit("结束绘制"), this);pAc1->setShortcut(QKeySequence("Ctrl+E"));QAction* pAc2 = new QAction(QString::fromLocal8Bit("清除"), this);pAc2->setShortcut(QKeySequence("Ctrl+D"));// 这是个假动作,为了让菜单消失,且不影响绘制路径QAction* pAc3 = new QAction(QString::fromLocal8Bit("退出菜单"), this);m_pMenu->addAction(pAc1);m_pMenu->addAction(pAc2);m_pMenu->addAction(pAc3);m_pMenu->setStyleSheet("QMenu{font:18px;}");connect(pAc1, &QAction::triggered, [=] {ui->graphicsPainter->endDraw();});connect(pAc2, &QAction::triggered, [=] {ui->graphicsPainter->clearPath();});
}MainWindow::~MainWindow()
{delete ui;
}// 右键菜单
void MainWindow::contextMenuEvent(QContextMenuEvent* event)
{m_pMenu->move(cursor().pos());m_pMenu->show();
}

完整代码:

#ifndef GRAPHICSPAINTER_H
#define GRAPHICSPAINTER_H#include <QWidget>class MyPainterWidget : public QWidget
{Q_OBJECTpublic:explicit MyPainterWidget(QWidget *parent = nullptr);void endDraw();void clearPath();protected:void paintEvent(QPaintEvent *) override;void mousePressEvent(QMouseEvent *e) override;       //按下void mouseMoveEvent(QMouseEvent *e) override;        //移动void mouseReleaseEvent(QMouseEvent *e) override;     //松开void mouseDoubleClickEvent(QMouseEvent *event) override;     //双击bool m_bStartDraw = false;    //是否已经开始左键点击,同时标识是否开始进行绘制bool bMove = false;           //是否处于绘制时的鼠标移动状态QVector<QPointF> pointList;QPointF movePoint;
};#endif // GRAPHICSPAINTER_H
#include "MyPainterWidget.h"
#include <QPainter>
#include <QMouseEvent>MyPainterWidget::MyPainterWidget(QWidget *parent) : QWidget(parent)
{setMouseTracking(true);pointList.clear();
}void MyPainterWidget::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.setPen(QColor(255,0,0));QVector<QLineF> lines;for(int i = 0; i < pointList.size()-1; i++){QLineF line(QPointF(pointList[i].x(), pointList[i].y()), QPointF(pointList[i+1].x(), pointList[i+1].y()));lines.push_back(line);}if (m_bStartDraw){int size = pointList.size();if (bMove && size > 0){QLineF line(QPointF(pointList[pointList.size() - 1].x(), pointList[pointList.size() - 1].y()),movePoint);lines.push_back(line);}}painter.drawLines(lines);
}// 按下
void MyPainterWidget::mousePressEvent(QMouseEvent *e)
{if (e->button() == Qt::LeftButton){if(!m_bStartDraw){pointList.clear();m_bStartDraw = true;}}   
}// 移动
void MyPainterWidget::mouseMoveEvent(QMouseEvent *e)
{if(m_bStartDraw){movePoint = e->pos();this->update();//重新进入painEvent事件进行绘制// 先刷新再设为true, 防止第一点和(0,0)连在一块bMove = true;}
}// 松开
void MyPainterWidget::mouseReleaseEvent(QMouseEvent *e)
{if (e->button() == Qt::LeftButton){if (m_bStartDraw){// 鼠标松开后的点需要添加到路径中pointList.push_back(QPointF(e->x(), e->y()));bMove = false;this->update();//刷新绘制}}
}// 双击结束绘制
void MyPainterWidget::mouseDoubleClickEvent(QMouseEvent *event)
{endDraw();
}void MyPainterWidget::endDraw()
{m_bStartDraw = false;//需要把第一个点连起来pointList.push_back(pointList[0]);this->update();
}void MyPainterWidget::clearPath()
{pointList.clear();this->update();
}

相关文章:

Qt实现绘制自定义形状

先创建一个继承自QWidget的控件&#xff1a; class MyPainterWidget:public QWidget 重写各种鼠标方法&#xff1a; protected:void paintEvent(QPaintEvent *) override;void mousePressEvent(QMouseEvent *e) override; //按下void mouseMoveEvent(QMouseEvent *e) …...

WordPress安装AWS插件实现文本转语音功能

适用于 WordPress 的 AWS 插件示例演示了内容创建者如何轻松地为所有书面内容添加文本转语音功能。随着语音搜索的不断增加&#xff0c;以音频格式提供更多网站内容变得至关重要。通过添加语音功能&#xff0c;网站访客可以通过在线音频播放器和播客应用程序等新渠道使用您的内…...

87-96-多维动态规划、技巧

LeetCode 热题 100 文章目录 LeetCode 热题 100多维动态规划87. 中等-不同路径88. 中等-最小路径和89. 中等-最长回文子串90. 中等-最长公共子序列91. 困难-编辑距离 技巧92. 简单-只出现一次的数字93. 简单-多数元素94. 中等-颜色分类95. 中等-下一个排列96. 中等-寻找重复数 …...

NX二次开发UF_CURVE_ask_wrap_curve_parents 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_wrap_curve_parents Defined in: uf_curve.h int UF_CURVE_ask_wrap_curve_parents(tag_t curve_tag, tag_t * defining_face, tag_t * defining_plane, tag_t * defin…...

使用 HTML、CSS 和 JavaScript 创建图像滑块

使用 HTML、CSS 和 JavaScript 创建轮播图 在本文中&#xff0c;我们将讨论如何使用 HTML、CSS 和 JavaScript 构建轮播图。我们将演示两种不同的创建滑块的方法&#xff0c;一种是基于opacity的滑块&#xff0c;另一种是基于transform的。 创建 HTML 我们首先从 HTML 代码开…...

ubuntu环境删除qtcreator方法

文章目录 方法1方法2方法3参考不同的安装方法,对应不同的删除方法 方法1 apt-get或者dpkg 方法2 QtCreatorUninstaller 方法3 MaintenanceTool...

软件测试基础知识

软件测试基本概念 1、软件程序文档&#xff0c;软件测试程序测试文档测试。 “程序”是指能够实现某种功能的指令的集合&#xff0c;“文档”是指软件在开发、使用和维护过程中产生的图文集合。&#xff1b; 2、软件的分类 按功能分&#xff1a;系统软件、应用软件 按技术架构分…...

使用 .toISOString() 方法生成当前时间的ISO格式字符串,解决UTC时区差问题

方法分析&#xff1a; 日常开发中&#xff0c;有时我们需要向后端传递的时间值可能并非一个时间对象&#xff0c;而是字符串格式。 例 1&#xff1a;[2023-08-16T08:07:25.577Z] 但是我们通过 new Date() 之后直接使用 .toString() 方法得到的却并非这种格式。 例 2&#xff1…...

“BMP转PNG一键转换,批量处理图片,迈入高效图片管理新时代“

你是否曾经为了转换图片格式而烦恼&#xff1f;是否曾经因为一张一张地手动转换而感到无奈&#xff1f;现在&#xff0c;我们的全新工具将为你解决这些问题&#xff0c;开启高效图片管理新时代&#xff01; 首先&#xff0c;我们进入首助编辑高手主页面&#xff0c;会看到有多种…...

解决Vue编程式导航路由跳转不显示目标路径问题

我们配置一个编程式导航的路由跳转&#xff0c;跳转到 /search 页面&#xff0c;并且携带categoryName和categoryId两个query参数。 this.$router.push({path: "/search",query: {categoryName: dataset.categoryname,categoryId: dataset.categoryid} }) 如果我们…...

Android studio 引用framework.jar

framework.jar 引用目录 N/O&#xff1a; out/target/common/obj/JAVA_LIBRARY/framework_interminate/classes.jarAndroid 9/10: out/soong/.intermediates/frameworks/base/framework/android_common/combined/framework.jarAndroid 11: out/soong/.intermediates/framewo…...

软著项目推荐 深度学习 python opencv 火焰检测识别 火灾检测

文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…...

宝塔面板安装搭建DiscuzQ论坛教程与小程序上架发布后的展示效果

DiscuzQ论坛小程序上架发布后的展示效果&#xff1a; 1、需要用到的环境&#xff1a; php7.2 mysql5.7或者MariaDB 10.2(我安装用的mysql8.0) php除了必要的一些扩展外&#xff0c;还需要启用readlink、symlink函数等&#xff0c;具体看官方说明&#xff0c;安装的时候也会提醒…...

交换机配置与管理

文档以国产迈普交换机为例&#xff0c;各厂家交换机配置有少许不同&#xff0c;仅供参考。 交换机命令行模式&#xff1a; 普通用户模式Hostname>&#xff08;&#xff09; exit 输入enable命令 特权用户模式Hostname#&#xff08;&#xff09; exit 输入configu…...

python每日一题——7接雨水

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表…...

Ubuntu20安装ssh服务

Ubuntu20上执行如下命令查看是否存在ssh服务 #ps -e | grep ssh 只有ssh-agent&#xff0c;没有sshd; 因此要安装openssh-server. 搜索openssh-server,得到下载链接&#xff1a; openssh-server 复制这个Binary Package链接即可下载&#xff0c;然后使用如下命令安装 sudo…...

linux LVM /dev/sdb mount dir /data【linux LVM 磁盘挂载目录】

添加磁盘 /dev/sdb rootregistry01 ~]# fdisk -lDisk /dev/sda: 53.7 GB, 53687091200 bytes, 104857600 sectors Units sectors of 1 * 512 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk lab…...

由于找不到msvcp120.dll无法继续执行代码是什么原因怎么修复

今天我想和大家分享的是关于“msvcp120.dll丢失的解决方法”。或许有些同学在平时使用电脑的过程中会遇到这个问题&#xff0c;但是并不知道该如何解决。那么&#xff0c;接下来我将从三个方面为大家介绍&#xff1a;msvcp120.dll丢失的原因、msvcp120.dll是什么以及msvcp120.d…...

为你的项目加上微信登录(个人开发)

当我们开发个人项目的时候&#xff0c;为了用户登录的便捷性&#xff0c;经常会给我们的项目加上一些除了注册之外的方式&#xff0c;其中最常见的就是微信登录&#xff0c;但作为个人开发者&#xff0c;是无法使用微信的授权登录的&#xff0c;但是通过微信公众号可以获得同样…...

Pinia的使用技巧

一、安装 npm install pinia 二、main.ts引入 import { createApp } from vue import App from ./App.vue import { createPinia } from piniaconst app createApp(App) app.use(createPinia()) app.mount(#app)三、定义参数 import { defineStore } from piniatype User …...

Zynq LWIP+DMA实战:如何高效传输250MSPS采样数据到PC(附MATLAB分析代码)

Zynq LWIPDMA高速数据传输实战&#xff1a;从硬件配置到MATLAB分析的完整链路优化 在嵌入式数据采集系统中&#xff0c;如何实现每秒2.5亿采样点&#xff08;250MSPS&#xff09;的高速ADC数据稳定传输至PC端&#xff0c;一直是工程师面临的棘手挑战。本文将揭示一套经过实际项…...

GIMP Resynthesizer终极指南:5步掌握智能纹理合成与图像修复

GIMP Resynthesizer终极指南&#xff1a;5步掌握智能纹理合成与图像修复 【免费下载链接】resynthesizer Suite of gimp plugins for texture synthesis 项目地址: https://gitcode.com/gh_mirrors/re/resynthesizer GIMP Resynthesizer是一套功能强大的GIMP纹理合成插件…...

3步解密Navicat密码:技术原理与实战应用完整指南

3步解密Navicat密码&#xff1a;技术原理与实战应用完整指南 【免费下载链接】navicat_password_decrypt 忘记navicat密码时,此工具可以帮您查看密码 项目地址: https://gitcode.com/gh_mirrors/na/navicat_password_decrypt 作为数据库开发者和管理员&#xff0c;你是否…...

告别硬件解码芯片?深度对比英飞凌TC3xx DSADC软解码方案与传统方案的优劣

英飞凌TC3xx DSADC软解码方案与传统硬件解码芯片的深度技术选型指南 在新能源汽车电机控制和工业伺服驱动系统的设计中&#xff0c;旋转变压器&#xff08;Resolver&#xff09;作为核心位置传感器&#xff0c;其解码方案的选择直接影响系统性能、成本和开发效率。传统方案依赖…...

Vue3 + SpringBoot实战:用Minio搞定大文件切片上传与断点续传(附完整前后端代码)

Vue3 SpringBoot全栈实战&#xff1a;基于Minio的工业级大文件上传系统设计 在当今数据爆炸的时代&#xff0c;处理大文件上传已成为现代Web应用的标配能力。想象一下这样的场景&#xff1a;用户正在上传一个10GB的设计文件&#xff0c;进度到90%时网络突然中断&#xff1b;或…...

VMware虚拟化环境部署FLUX小红书V2:隔离开发环境搭建指南

VMware虚拟化环境部署FLUX小红书V2&#xff1a;隔离开发环境搭建指南 1. 环境准备与虚拟机配置 在开始部署FLUX小红书V2之前&#xff0c;我们需要先搭建一个合适的虚拟化环境。VMware作为业界领先的虚拟化平台&#xff0c;能够为我们提供稳定且高性能的隔离开发环境。 首先确…...

从音频到体重秤:聊聊那些‘看不见’的Delta-Sigma ADC在你身边的真实应用

从音频到体重秤&#xff1a;Delta-Sigma ADC如何重塑日常测量的精度边界 当你用蓝牙耳机聆听192kHz高解析音频时&#xff0c;或在智能体脂秤上看到小数点后两位的体重变化时&#xff0c;可能不会想到这些体验背后都藏着一项诞生于1980年代的革命性技术——Delta-Sigma ADC&…...

工业五官:11 老鸟血泪Tips + 新手避坑清单

11 老鸟血泪Tips + 新手避坑清单 卷一“工业生命的诞生——从大脑到五官”第三篇终于来了!工业五官——传感器的超级感知世界!PLC是大脑,机器人是舞伴,伺服是肌肉,那这些传感器就是“眼睛、耳朵、鼻子、手”啊!没它们,机器就是瞎子聋子,啤酒瓶来了也不知道推,哈哈。以…...

环境监测系统:空气质量与水质数据的实时分析

环境监测系统&#xff1a;守护呼吸与生命之源 在城市化与工业化快速发展的今天&#xff0c;空气质量与水质安全已成为公众关注的焦点。环境监测系统通过实时采集、分析空气和水质数据&#xff0c;为污染预警、生态保护及政策制定提供科学依据。这项技术不仅关乎人类健康&#…...

Pixel Dream Workshop 企业级应用:基于 Agent 架构的自动化设计工作流

Pixel Dream Workshop 企业级应用&#xff1a;基于 Agent 架构的自动化设计工作流 1. 企业内容创作的痛点与机遇 在数字化营销时代&#xff0c;企业每天需要生产大量视觉内容——从社交媒体配图到产品详情页&#xff0c;从广告海报到活动宣传物料。传统设计流程面临三大核心挑…...