使用QT绘制一个多边形
1. 概述
可以通过QT的重绘事件和鼠标事件来绘制多边形,最简单的办法就是在继承QWidget的窗体中重写paintEvent、mousePressEvent等事件处理函数。QT提供了图形绘制接口QPainter,通过该接口可以绘制多种图形,包括多边形。
2. 实现
2.1. 代码
新建一个基于QWidget的QT界面类GraphicsPainter,将其放置到想要显示的窗体中。该类的具体代码:
GraphicsPainter.h:
#ifndef GRAPHICSPAINTER_H
#define GRAPHICSPAINTER_H
#include <QWidget>
class GraphicsPainter : public QWidget
{
Q_OBJECT
public:
explicit GraphicsPainter(QWidget *parent = nullptr);
void SetDraw(bool bDraw);
signals:
void singalDrawOver();
public slots:
protected:
void paintEvent(QPaintEvent *); //绘制
void mousePressEvent(QMouseEvent *e); //按下
void mouseMoveEvent(QMouseEvent *e); //移动
void mouseReleaseEvent(QMouseEvent *e); //松开
void mouseDoubleClickEvent(QMouseEvent *event); //双击
bool bDraw; //是否处于绘制状态
bool bLeftClick; //是否已经开始左键点击,同时标识是否开始进行绘制
bool bMove; //是否处于绘制时的鼠标移动状态
QVector<QPointF> pointList;
QPointF movePoint;
};
#endif // GRAPHICSPAINTER_H
GraphicsPainter.cpp:
#include "graphicspainter.h"
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>
GraphicsPainter::GraphicsPainter(QWidget *parent) : QWidget(parent)
{
//填充背景色
setAutoFillBackground(true);
setBackgroundRole(QPalette::Base);
bDraw = false;
bLeftClick = false;
bMove = false;
setMouseTracking(true);
}
void GraphicsPainter::SetDraw(bool bDraw)
{
this->bDraw = bDraw;
pointList.clear();
}
//重新实现paintEvent
void GraphicsPainter::paintEvent(QPaintEvent *)
{
QPainter painter(this);
if(bDraw)
{
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(bMove&&pointList.size()>0)
{
QLineF line(QPointF(pointList[pointList.size()-1].x(), pointList[pointList.size()-1].y()), movePoint);
lines.push_back(line);
}
painter.drawLines(lines);
}
}
//按下
void GraphicsPainter::mousePressEvent(QMouseEvent *e)
{
if(bDraw)
{
if(!bLeftClick)
{
pointList.clear();
bLeftClick = true;
}
}
//qDebug()<<"Press";
}
//移动
void GraphicsPainter::mouseMoveEvent(QMouseEvent *e)
{
if(bDraw&&bLeftClick)
{
movePoint = e->pos();
bMove = true;
this->update();
}
//qDebug()<<"Move";
}
//松开
void GraphicsPainter::mouseReleaseEvent(QMouseEvent *e)
{
if(bDraw&&bLeftClick)
{
pointList.push_back(QPointF(e->x(), e->y()));
bMove = false;
this->update();
}
//qDebug()<<"Release";
}
//双击
void GraphicsPainter::mouseDoubleClickEvent(QMouseEvent *event)
{
if(bDraw)
{
bLeftClick = false;
pointList.push_back(pointList[0]);
this->update();
singalDrawOver();
}
//qDebug()<<"DoubleClick";
}
2.2. 解析
在重新实现的重绘事件中,通过QPainter绘制了一系列线组成线串,最后会首尾相连形成多边形。这里的bMove标识是否处于绘制时的鼠标移动状态,只有鼠标左键点击后才会确定为真正的节点:
//重新实现paintEvent
void GraphicsPainter::paintEvent(QPaintEvent *)
{
QPainter painter(this);
if(bDraw)
{
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(bMove&&pointList.size()>0)
{
QLineF line(QPointF(pointList[pointList.size()-1].x(), pointList[pointList.size()-1].y()), movePoint);
lines.push_back(line);
}
painter.drawLines(lines);
}
}
鼠标按下事件中,主要是通过bLeftClick值来确定是否已经处于左键点击状态,同时还能标识是否开始进行绘制。一旦开始,就会把上次绘制的节点清除。
//按下
void GraphicsPainter::mousePressEvent(QMouseEvent *e)
{
if(bDraw)
{
if(!bLeftClick)
{
pointList.clear();
bLeftClick = true;
}
}
//qDebug()<<"Press";
}
一旦鼠标松开,就可以确定一个节点,此时需要调用update()进行重绘:
//松开
void GraphicsPainter::mouseReleaseEvent(QMouseEvent *e)
{
if(bDraw&&bLeftClick)
{
pointList.push_back(QPointF(e->x(), e->y()));
bMove = false;
this->update();
}
//qDebug()<<"Release";
}
当开始进行绘制后,移动鼠标就会处于绘制时的鼠标移动状态,这时就会确定bMove为true,重绘事件就会将该鼠标点绘制出来,从而达到待选节点的效果:
//移动
void GraphicsPainter::mouseMoveEvent(QMouseEvent *e)
{
if(bDraw&&bLeftClick)
{
movePoint = e->pos();
bMove = true;
this->update();
}
//qDebug()<<"Move";
}
鼠标双击后,将第一个点加入到当前多边形的节点中后,达到首尾相连的效果,此时就会结束绘制:
//双击
void GraphicsPainter::mouseDoubleClickEvent(QMouseEvent *event)
{
if(bDraw)
{
bLeftClick = false;
pointList.push_back(pointList[0]);
this->update();
singalDrawOver();
}
//qDebug()<<"DoubleClick";
}
这里一定要注意,当进行双击操作时,首先会触发一次mousePressEvent,然后触发一次mouseReleaseEvent,接着才会触发一次mouseDoubleClickEvent,最后还会触发一次mouseReleaseEvent。所以这就是这里设置bLeftClick这个参数原因:当触发mouseDoubleClickEvent后,bLeftClick设置为false,第二次触发mouseReleaseEvent时内部就不会在做任何操作了。
3. 结果
最终运行的结果如下所示:

使用QT绘制一个多边形的更多相关文章
- IOS 中openGL使用教程2(openGL ES 入门篇 | 绘制一个多边形)
在上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形. 在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> ...
- iOS-----openGL--openGL ES iOS 入门篇2--->绘制一个多边形
在上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形. 在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> ...
- Qt使用一个事件队列对所有发出的事件进行维护(QObject的event()函数相当于dispatch函数),用EventLabel 继承QLabel作为例子(简单明了) good
事件(event)是由系统或者 Qt 本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应时发出,如键盘事件等:另一些事 ...
- MFC 用gdi绘制填充多边形区域
MFC 用gdi绘制填充多边形区域 这里的代码是实现一个三角形的绘制,并用刷子填充颜色 在OnPaint()函数里面 运用的是给定的三角形的三个点,很多个点可以绘制多边形 CBrush br(RGB( ...
- Opentk教程系列-1绘制一个三角形
本系列教程翻译自Neo Kabuto's Blog.已经取得作者授权. 本文原文地址http://neokabuto.blogspot.com/2013/02/opentk-tutorial-1-op ...
- OpenTK教程-1绘制一个三角形
OpenTK的官方文档是真心的少,他们把怎么去安装OpenTK说的很清楚,但是也就仅限于此,这有一篇learn opentk in 15的教程(链接已经失效,译者注),但是并不完美.你可以在15分钟内 ...
- Qt 学习之路 2(24):Qt 绘制系统简介
Qt 学习之路 2(24):Qt 绘制系统简介 豆子 2012年10月30日 Qt 学习之路 2 77条评论 Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制.整个绘图系统基于Q ...
- [原译]WPF绘制圆角多边形
原文:[原译]WPF绘制圆角多边形 介绍 最近,我发现我需要个圆角多边形.而且是需要在运行时从用户界面来绘制.WPF有多边形.但是不支持圆角.我搜索了一下.也没找到可行的现成例子.于是就自己做吧.本文 ...
- Qt 模拟一个导航定位系统
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/lihuidashen/p/115397 ...
随机推荐
- Ubuntu 设置静态 IP
一.背景 如果没有设置静态IP,由于某些情况,会导致系统的 IP 地址发生变化. 为了避免 IP 发生变化,就需要进行静态 IP 的设置. 注:这里 Ubuntu 版本为 19.10 二.解决方案 1 ...
- [Usaco2009 Oct]Heat Wave 热浪(裸最短路径)
链接:https://ac.nowcoder.com/acm/contest/1082/F来源:牛客网 题目描述 The good folks in Texas are having a heatwa ...
- TOJ-3474 The Big Dance(递归二分)
链接:https://ac.nowcoder.com/acm/contest/1077/L 题目描述 Bessie and the herd, N (1 <= N <= 2,200) co ...
- linux系统用户管理(二)
5.组命令管理**组账户信息保存在/etc/group和/etc/gshadow两个文件中 /etc/group 组账户信息 [root@localhost ~]# head -2 /etc/grou ...
- Minimum Sum
题目描述 One day, Snuke was given a permutation of length N, a1,a2,…,aN, from his friend. Find the follo ...
- bean加载与注入之重新理解
1.@Autowired注解不可以用在静态属性上: 解决方法: 使用实现了ApplicationContextAware接口的自定义工具类,ApplicationContextAware可以让我们获得 ...
- python中安装surprise中出现error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools":
pip安装 安装之前要先进行numpy的安装 pip install numpy pip install surprise 安装出错: 安装surprise需要Microsoft visual c++ ...
- python学习笔记(11)文件操作
一.读文件 读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的. 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直 ...
- CDN是什么鬼
CDN,内容分发网络,是大多数互联网业务里必不可少的部分,但大多数互联网从业人员不是特别清楚CDN究竟是什么,以及它可以为我们做哪些事情. 我们还是从之前介绍的<不同的人看到的直播为什么不一样? ...
- 为什么说iPhone无望恢复中国市场?
直到现在还记得,iPhone 4在国内当时引发的追捧狂潮.彼时iPhone 4绝对是一机难求,上至土豪下至学生都以拥有iPhone 4为荣.发售接近一年后仍然需要加价,价格动辄达到七八千元,真正成为了 ...