Qt实现绘制一个简单多边形的示例代码

 更新时间:2022年11月24日 08:47:02   作者:音视频开发老舅  
QT提供了图形绘制接口QPainter,通过该接口可以绘制多种图形,包括多边形。本文就来利用它实现绘制一个简单的多边形,感兴趣的可以尝试一下

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实现绘制一个简单多边形的示例代码的文章就介绍到这了,更多相关Qt绘制多边形内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言实现计算树的深度的方法

    C语言实现计算树的深度的方法

    这篇文章主要介绍了C语言实现计算树的深度的方法,针对数据结构中树进行操作的方法,在算法设计中比较常见,需要的朋友可以参考下
    2014-09-09
  • 如何在Qt中实现关于Json 的操作

    如何在Qt中实现关于Json 的操作

    JSON是一种轻量级数据交换格式,常用于客户端和服务端的数据交互,不依赖于编程语言,在很多编程语言中都可以使用JSON,这篇文章主要介绍了在Qt中实现关于Json的操作,需要的朋友可以参考下
    2023-08-08
  • C++中事件机制的简洁实现及需要放弃的特性

    C++中事件机制的简洁实现及需要放弃的特性

    事件模型是被广泛使用的好东西,但是C++标准库里没有现成的,现在VC11可以用在XP下了,那么就痛快的拿起C++11提供的先进设施组合出一个轻便的实现吧感兴趣的朋友可以了解下,或许对你有所帮助
    2013-02-02
  • 深度理解c++中的this指针

    深度理解c++中的this指针

    这篇文章主要介绍了C++编程指向成员的指针以及this指针的基本使用指南,与C语言一样,存储的数值被解释成为内存里的一个地址,需要的朋友可以参考下。
    2016-07-07
  • 深入二叉树两个结点的最低共同父结点的详解

    深入二叉树两个结点的最低共同父结点的详解

    本篇文章是对二叉树两个结点的最低共同父结点进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • VScode中C++头文件问题的终极解决方法详析

    VScode中C++头文件问题的终极解决方法详析

    最近使用VSCode编译C/C++时发现了问题,下面这篇文章主要给大家介绍了关于VScode中C++头文件问题的终极解决方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • LintCode 堆化详解及实例代码

    LintCode 堆化详解及实例代码

    这篇文章主要介绍了LintCode 堆化详解及实例代码的相关资料,需要的朋友可以参考下
    2017-04-04
  • C语言中的getchar()使用详解

    C语言中的getchar()使用详解

    大家好,本篇文章主要讲的是C语言中的getchar()使用详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • C++ Boost Flyweight库使用介绍

    C++ Boost Flyweight库使用介绍

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-12-12
  • C语言类型转换与常量的细节深入理解探究

    C语言类型转换与常量的细节深入理解探究

    这篇文章主要为大家介绍了C 语言类型转换与常量的细节深入理解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12

最新评论