当前位置: 首页 > 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 …...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...