zoukankan      html  css  js  c++  java
  • 使用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绘制多边形

    代码地址

  • 相关阅读:
    Laex/Delphi-OpenCV
    webbrowser 防止读取 缓存
    tesnsorflow 版本安装错了。 可以这样删除。
    python中%代表什么意思?
    python 访问 网页 获得源码
    3.2.2 break 与 continue 语句
    3.2.1 for循环与while循环的基本语法
    3.2 循环结构
    3.1.2 选择结构的几种形式
    3.1.1 条件表达式
  • 原文地址:https://www.cnblogs.com/charlee44/p/12426827.html
Copyright © 2011-2022 走看看